尝试通过谷歌驱动器API获取文档元数据时出现404错误 [英] 404 Error when trying to get document metadata via the google drive API

查看:451
本文介绍了尝试通过谷歌驱动器API获取文档元数据时出现404错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用全域代表团进行身份验证。



我回来了看起来像这样的谷歌驱动器服务: com.google.api.services.drive.Drive@6ebd27b9

这是我试图检索的文件的链接: https://docs.google.com/a /rmi.org/document/d/1JRS8SLzaAD2U4cG-GbDMbVN25Dp6f_uUYyl6ERMPAno/edit



我将这个值作为文件ID传递: 1JRS8SLzaAD2U4cG-GbDMbVN25Dp6f_uUYyl6ERMPAno



当代码到达这一行时: File file = service.files( ).get(fileId).execute();



我得到这个错误:

 发生错误:com.google.api.client.googleapis.json.GoogleJsonResponseException:404 OK 
{
code:404,
errors:[{
domain:global,
message:File not found:1JRS8SLzaAD2U4cG-GbDMbVN25Dp6f_uUYyl6ERMPAno,
reason:notFound
$]],

当我尝试使用工具底部此页,如果我打开Oauth 2.0,我会得到返回一个200响应代码和有关该文件的信息。



我已经看过很多类似的问题,包括

未选中双腿OAuth访问控制允许访问所有API >

这里是我获得驱动器服务的地方:

  public static Drive getDriveService )throws GeneralSecurityException,
IOException,URISyntaxException {

HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
GoogleCredential凭证=新GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
//.setServiceAccountScopes(DriveScopes .DRIVE)
.setServiceAccountScopes(SCOPE)
.setServiceAccountPrivateKeyFromP12File(
new java.io.File(SERVICE_ACCOUNT_PKCS12_FILE_PATH))
.build();
Drive service = new Drive.Builder(httpTransport,jsonFactory,null)
.setHttpRequestInitializer(凭证).build();
退货服务;

我有这些变量定义如下:

  / **服务帐户的电子邮件* / 
private static final String SERVICE_ACCOUNT_EMAIL =xxxxxxxxxxxxxxxxxxxxxxxxxxxxx@developer.gserviceaccount.com;

**服务帐户私钥文件的路径* /
private static final String SERVICE_ACCOUNT_PKCS12_FILE_PATH =/actualpathhere/HowToListing/war/resources/actualpd12filename.p12;
private static final List< String> SCOPE = Arrays.asList(https://www.googleapis.com/auth/drive.readonly);

这里是我试图获取文件元数据的地方:

  private static List< File> retrieveAllFiles(Drive service)抛出IOException {
List< File> result = null;
尝试{
字符串fileId =1JRS8SLzaAD2U4cG-GbDMbVN25Dp6f_uUYyl6ERMPAno;
File file = service.files()。get(fileId).execute();
System.out.println(Title:+ file.getTitle());
System.out.println(Description:+ file.getDescription());
System.out.println(MIME type:+ file.getMimeType());
$ b $ catch(IOException e){
System.out.println(发生错误:+ e);
}


返回结果;
}

任何人都可以提供关于可能发生的事情的任何提示吗?

解决方案

EDITED

一个红色的鲱鱼,事实证明。缺少的关键是有效的用户的电子邮件地址。首先,运行代码:

  import java.io.IOException; 
import java.net.URL;
import java.security.GeneralSecurityException;
import java.util.Arrays;

导入com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
导入com.google.api.services.drive.Drive;
导入com.google.api.services.drive.DriveScopes;
导入com.google.api.services.drive.model.File;


公共类DriveCommandLine {


私有静态字符串SERVICE_ACCOUNT_EMAIL =11111-abc123@developer.gserviceaccount.com;
private static final String SERVICE_ACCOUNT_PKCS12_FILE_NAME =a_file_name.p12;
private static String SERVICE_ACCOUNT_PKCS12_FILE_PATH;

public static void main(String [] args)throws IOException {
try {
//我为p12文件做了这些事b / c我在做这件事时遇到了麻烦全部来自命令行(第一次)
URL位置= DriveCommandLine.class.getProtectionDomain()。getCodeSource()。getLocation();
SERVICE_ACCOUNT_PKCS12_FILE_PATH = location.getFile()+ SERVICE_ACCOUNT_PKCS12_FILE_NAME;

驱动器驱动器= DriveCommandLine.getDriveService(valid-user@example.com);
DriveCommandLine.printFile(驱动器,THE_ID_OF_THE_FILE);
} catch(GeneralSecurityException e){
// TODO自动生成的catch块
e.printStackTrace();
}
}

//从https://developers.google.com/drive/web/delegation#instantiate_a_drive_service_object
/ **
*构建并返回授权服务帐户
*代表给定用户的Drive服务对象。
*
* @param userEmail用户的电子邮件。
* @return准备发出请求的驱动器服务对象。
* /
public static Drive getDriveService(String userEmail)throws GeneralSecurityException,IOException {
HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
GoogleCredential凭证=新的GoogleCredential.Builder()。setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(Arrays.asList(new String [ ] {
.setServiceAccountUser(userEmail)
.setServiceAccountPrivateKeyFromP12File(new java.io.File(SERVICE_ACCOUNT_PKCS12_FILE_PATH))
.build();
Drive service = new Drive.Builder(httpTransport,jsonFactory,null).setHttpRequestInitializer(credential).build();
退货服务;
}
//从https://developers.google.com/drive/v2/reference/files/get
/ **
中的代码框中打印文件元数据。
*
* @param服务Drive API服务实例。
* @param fileId要打印元数据的文件的ID。
* /
private static void printFile(Drive service,String fileId){

try {
File file = service.files()。get(fileId)。执行();

System.out.println(Title:+ file.getTitle());
System.out.println(Description:+ file.getDescription());
System.out.println(MIME type:+ file.getMimeType());
catch(IOException e){
System.out.println(发生错误:+ e);
}
}
}

缺少的行是 setServiceAccountUser(userEmail)这是一个有效的系统用户。



使用有效的用户,我得到了文件详细信息。 / p>

使用无效用户时,我得到了

 发生错误:com .google.api.client.auth.oauth2.TokenResponseException:400错误请求
{
错误:invalid_grant,
error_description:不是有效的电子邮件。
}

而且,对于没有访问权限的用户或者行不是set,我得到了

 发生了一个错误:com.google.api.client.googleapis.json.GoogleJsonResponseException:404 Not Found 
{
code:404,
errors:[{
domain:global,
message:File not found:THE_FILE_ID ,
reason:notFound
}],
message:File not found:THE_FILE_ID
}

注意:请确保您遵循执行Google Apps域范围授权,因为这是我最终获得解决方案和所有正确密钥的地方(不需要像我最初想象的那样多!)

I am authenticating using domain-wide delegation.

I am getting back the google drive service that looks like this: com.google.api.services.drive.Drive@6ebd27b9

This is the link to the file I'm trying to retrieve: https://docs.google.com/a/rmi.org/document/d/1JRS8SLzaAD2U4cG-GbDMbVN25Dp6f_uUYyl6ERMPAno/edit

I am passing in this value as the file ID: 1JRS8SLzaAD2U4cG-GbDMbVN25Dp6f_uUYyl6ERMPAno.

When the code gets to this line: File file = service.files().get(fileId).execute();

I get this error:

An error occured: com.google.api.client.googleapis.json.GoogleJsonResponseException: 404 OK
{
"code" : 404,
"errors" : [ {
"domain" : "global",
"message" : "File not found: 1JRS8SLzaAD2U4cG-GbDMbVN25Dp6f_uUYyl6ERMPAno",
"reason" : "notFound"
 } ],

When I try to find the file in question using the tool at the bottom of this page, if I turn on Oauth 2.0, I get back a 200 response code and information about the file in question.

I've looked at many similar questions on here including this question, but I can't see anything wrong in the way that I've set up my permissions:

  • For my project, both the Drive API and Drive SDK are on under APIs and Auth.
  • Under Credentials I see my client ID, Email addresss and Public Key fingerprints
  • I've also verified on my domain's admin console that under security > API reference, enable API access is checked.
  • Security > Advanced Settings > Manage API Client Access the following scope is added: https://www.googleapis.com/auth/drive with the service account's client ID.
  • Security > Advanced > Manage Oauth Domain key:
    • The "enable this consumer key" checkbox is checked.
    • There is an oAuth consumer secret code.
    • There is no X.509 certificate.
    • The "two legged OAuth access control Allow access to all APIs" is unchecked.

Here is where I get the drive service:

        public static Drive getDriveService() throws GeneralSecurityException,
    IOException, URISyntaxException {

  HttpTransport httpTransport = new NetHttpTransport();
  JacksonFactory jsonFactory = new JacksonFactory();
  GoogleCredential credential = new GoogleCredential.Builder()
      .setTransport(httpTransport)
      .setJsonFactory(jsonFactory)
      .setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
      //.setServiceAccountScopes(DriveScopes.DRIVE)
      .setServiceAccountScopes(SCOPE)
      .setServiceAccountPrivateKeyFromP12File(
          new java.io.File(SERVICE_ACCOUNT_PKCS12_FILE_PATH))
      .build();
  Drive service = new Drive.Builder(httpTransport, jsonFactory, null)
      .setHttpRequestInitializer(credential).build();
  return service;

I have these variables defined as follows:

/** Email of the Service Account */
private static final String SERVICE_ACCOUNT_EMAIL = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx@developer.gserviceaccount.com";

/** Path to the Service Account's Private Key file */
private static final String SERVICE_ACCOUNT_PKCS12_FILE_PATH = "/actualpathhere/HowToListing/war/resources/actualpd12filename.p12"; 
private static final List<String> SCOPE = Arrays.asList("https://www.googleapis.com/auth/drive.readonly");

Here is where I am trying to get the file metadata:

private static List<File> retrieveAllFiles(Drive service) throws IOException {
        List<File> result = null;
        try {
            String fileId = "1JRS8SLzaAD2U4cG-GbDMbVN25Dp6f_uUYyl6ERMPAno";
            File file = service.files().get(fileId).execute();
            System.out.println("Title: " + file.getTitle());
            System.out.println("Description: " + file.getDescription());
            System.out.println("MIME type: " + file.getMimeType());

          } catch (IOException e) {
            System.out.println("An error occured: " + e);
          }


        return result;
      }

Can anyone give me any hints as to what might be going on?

解决方案

EDITED

All the security was a red herring, it turns out. The key thing missing was a valid user's email address. First, functioning code:

import java.io.IOException;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.util.Arrays;

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.File;


public class DriveCommandLine {


  private static String SERVICE_ACCOUNT_EMAIL  = "11111-abc123@developer.gserviceaccount.com";
  private static final String SERVICE_ACCOUNT_PKCS12_FILE_NAME = "a_file_name.p12";
  private static String SERVICE_ACCOUNT_PKCS12_FILE_PATH; 

  public static void main(String[] args) throws IOException {
    try {
      //I did this stuff for the p12 file b/c I was having trouble doing this all from command line (first time)
      URL location = DriveCommandLine.class.getProtectionDomain().getCodeSource().getLocation();
      SERVICE_ACCOUNT_PKCS12_FILE_PATH = location.getFile() + SERVICE_ACCOUNT_PKCS12_FILE_NAME;

      Drive drive = DriveCommandLine.getDriveService("valid-user@example.com");
      DriveCommandLine.printFile(drive, "THE_ID_OF_THE_FILE");
    } catch (GeneralSecurityException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

  //From https://developers.google.com/drive/web/delegation#instantiate_a_drive_service_object
  /**
   * Build and returns a Drive service object authorized with the service accounts
   * that act on behalf of the given user.
   *
   * @param userEmail The email of the user.
   * @return Drive service object that is ready to make requests.
   */
  public static Drive getDriveService(String userEmail) throws GeneralSecurityException, IOException {
    HttpTransport httpTransport = new NetHttpTransport();
    JacksonFactory jsonFactory = new JacksonFactory();
    GoogleCredential credential = new GoogleCredential.Builder().setTransport(httpTransport)
                                                                .setJsonFactory(jsonFactory)
                                                                .setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
                                                                .setServiceAccountScopes(Arrays.asList(new String[] {DriveScopes.DRIVE}))
                                                                .setServiceAccountUser(userEmail)
                                                                .setServiceAccountPrivateKeyFromP12File(new java.io.File(SERVICE_ACCOUNT_PKCS12_FILE_PATH))
                                                                .build();
    Drive service = new Drive.Builder(httpTransport, jsonFactory, null).setHttpRequestInitializer(credential).build();
    return service;
  }
  // From the code box at https://developers.google.com/drive/v2/reference/files/get
  /**
   * Print a file's metadata.
   *
   * @param service Drive API service instance.
   * @param fileId ID of the file to print metadata for.
   */
  private static void printFile(Drive service, String fileId) {

    try {
      File file = service.files().get(fileId).execute();

      System.out.println("Title: " + file.getTitle());
      System.out.println("Description: " + file.getDescription());
      System.out.println("MIME type: " + file.getMimeType());
    } catch (IOException e) {
      System.out.println("An error occured: " + e);
    }
  }
}

The missing line was setServiceAccountUser(userEmail) which is for a valid system user.

With a valid user, I got the file details.

With an invalid user, I got

An error occured: com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request
{
  "error" : "invalid_grant",
  "error_description" : "Not a valid email."
}

And, with a user who did not have access or when the line was not set, I got

An error occured: com.google.api.client.googleapis.json.GoogleJsonResponseException: 404 Not Found
{
  "code" : 404,
  "errors" : [ {
    "domain" : "global",
    "message" : "File not found: THE_FILE_ID",
    "reason" : "notFound"
  } ],
  "message" : "File not found: THE_FILE_ID"
}

NOTE: Just be sure you follow each little step at Perform Google Apps Domain-Wide Delegation of Authority since that is where I ended up getting the solution and all the right keys (didn't need as many as I initially thought!)

这篇关于尝试通过谷歌驱动器API获取文档元数据时出现404错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆