appdata范围内无法更新文件存储 – 500内部服务器错误

以前,我有一套Google Drive API代码,在以下情况下可以正常使用

  1. 将新文件保存到appdata
  2. 在appdata中更新以前的文件
  3. 将新文件保存到非appdata
  4. 更新非appdata中的上一个文件

几天前,我遇到方案2不再工作(更新appdata中的上一个文件),而其他方案仍然没有问题。 我将得到以下exception。

com.google.api.client.googleapis.json.GoogleJsonResponseException: 500 Internal Server Error { "code": 500, "errors": [ { "domain": "global", "message": "Internal Error", "reason": "internalError" } ], "message": "Internal Error" } at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:145) at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:113) at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:40) at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:423) at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:343) at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:460) at org.yccheok.jstock.gui.Utils.updateFile(Utils.java:1414) 

我正在使用DRIVEDRIVE_APPDATA范围 – authorizeDrive()

代码如下

  • saveToGoogleDrive() – 在appdata中保存或更新文件, 在更新文件期间不起作用 。 保存新文件时工作。
  • saveToLegacyGoogleDrive() – 在非appdata中保存或更新文件 ,一切正常!

1414号线正在抛出exception

 com.google.api.services.drive.model.File updatedFile = service.files().update(fileId, file, mediaContent).setNewRevision(false).execute(); 

使用查询title contains 'jstock-fe78440e-e0fe-4efb' and trashed = false and 'appdata' in parents在appdata中搜索上一个文件title contains 'jstock-fe78440e-e0fe-4efb' and trashed = false and 'appdata' in parents完全没问题。 我们能够毫无问题地检索以前的文件ID。

但是,当我们使用检索到的文件ID执行文件更新时,将引发500 Internal Server Error

一些用户在appdata中搜索时遇到问题(这不是我的情况)。 “appdata”文件夹中的搜索文件夹建议的解决方法是添加drive.readonly.metadata 。 我曾尝试过一次,但没有任何区别。


更新

Jon Skeet提出了一个很好的解决方法

我设法重现了这个问题。 没有setNewRevision(false)它可以工作 – 我意识到在所有情况下可能都不可行,但对你来说这是一个合理的解决方法吗?

但是,我现在暂时停止这种解决方法。 我们更喜欢使用setNewRevision(false) ,以防止更多地使用用户的数据存储配额 – http://developers.google.com/drive/v2/reference/files/update


简短但完整的源代码来演示问题

  1. 创建客户端ID和密钥。 更新源代码。
  2. 创建document.txt
  3. 首次运行源代码,将document.txt上传到appdata文件夹。 它应该成功。 通过在线Google云端硬盘查看您上传的文件。 (请参阅附件)
  4. 第二次运行源代码,以在appdata文件夹中的先前document.txt上执行更新。 应抛出500 Internal Server Errorexception。

在此处输入图像描述

 /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package insert; import com.google.api.client.auth.oauth2.Credential; import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow; import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; import com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse; import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; import com.google.api.client.http.FileContent; import com.google.api.client.http.HttpTransport; import com.google.api.client.json.gson.GsonFactory; import com.google.api.services.drive.Drive; import com.google.api.services.drive.DriveScopes; import com.google.api.services.drive.model.FileList; import com.google.api.services.drive.model.ParentReference; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.security.GeneralSecurityException; import java.util.Arrays; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class Insert { private static com.google.api.services.drive.model.File searchFromGoogleDrive(Drive drive, String qString) { try { Drive.Files.List request = drive.files().list().setQ(qString); do { FileList fileList = request.execute(); com.google.api.services.drive.model.File file = null; for (com.google.api.services.drive.model.File f : fileList.getItems()) { final String title = f.getTitle(); if (title == null || f.getDownloadUrl() == null || f.getDownloadUrl().length()  0); } catch (IOException ex) { log.error(null, ex); return null; } return null; } public static boolean saveToGoogleDrive(Credential credential, java.io.File file) { final String titleName = "document.txt"; final String qString = "title contains '" + titleName + "' and trashed = false and 'appdata' in parents"; return _saveToGoogleDrive(credential, file, qString, "appdata"); } public static Drive getDrive(Credential credential) { Drive service = new Drive.Builder(httpTransport, JSON_FACTORY, credential).setApplicationName("JStock").build(); return service; } private static boolean _saveToGoogleDrive(Credential credential, java.io.File file, String qString, String folder) { Drive drive = getDrive(credential); // Should we new or replace? com.google.api.services.drive.model.File googleCloudFile = searchFromGoogleDrive(drive, qString); final String title = "document.txt"; if (googleCloudFile == null) { String id = null; if (folder != null) { com.google.api.services.drive.model.File appData; try { appData = drive.files().get(folder).execute(); id = appData.getId(); } catch (IOException ex) { log.error(null, ex); return false; } } return null != insertFile(drive, title, id, file); } else { final com.google.api.services.drive.model.File oldFile = googleCloudFile; return null != updateFile(drive, oldFile.getId(), title, file); } } /** * Insert new file. * * @param service Drive API service instance. * @param title Title of the file to insert, including the extension. * @param parentId Optional parent folder's ID. * @param mimeType MIME type of the file to insert. * @param filename Filename of the file to insert. * @return Inserted file metadata if successful, {@code null} otherwise. */ private static com.google.api.services.drive.model.File insertFile(Drive service, String title, String parentId, java.io.File fileContent) { // File's metadata. com.google.api.services.drive.model.File body = new com.google.api.services.drive.model.File(); body.setTitle(title); // Set the parent folder. if (parentId != null && parentId.length() > 0) { body.setParents( Arrays.asList(new ParentReference().setId(parentId))); } // File's content. FileContent mediaContent = new FileContent("", fileContent); try { com.google.api.services.drive.model.File file = service.files().insert(body, mediaContent).execute(); return file; } catch (IOException e) { log.error(null, e); return null; } } /** * Update an existing file's metadata and content. * * @param service Drive API service instance. * @param fileId ID of the file to update. * @param newTitle New title for the file. * @param newFilename Filename of the new content to upload. * @return Updated file metadata if successful, {@code null} otherwise. */ private static com.google.api.services.drive.model.File updateFile(Drive service, String fileId, String newTitle, java.io.File fileContent) { try { // First retrieve the file from the API. com.google.api.services.drive.model.File file = service.files().get(fileId).execute(); // File's new metadata. file.setTitle(newTitle); FileContent mediaContent = new FileContent("", fileContent); // Send the request to the API. com.google.api.services.drive.model.File updatedFile = service.files().update(fileId, file, mediaContent).setNewRevision(false).execute(); return updatedFile; } catch (IOException e) { log.error(null, e); return null; } } private static String CLIENT_ID = "CLIENT_ID"; private static String CLIENT_SECRET = "CLIENT_SECRET"; private static String REDIRECT_URI = "urn:ietf:wg:oauth:2.0:oob"; public static void main(String[] args) throws IOException { GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder( httpTransport, JSON_FACTORY, CLIENT_ID, CLIENT_SECRET, Arrays.asList(DriveScopes.DRIVE_APPDATA, DriveScopes.DRIVE)) .setAccessType("online") .setApprovalPrompt("auto").build(); String url = flow.newAuthorizationUrl().setRedirectUri(REDIRECT_URI).build(); System.out.println("Please open the following URL in your browser then type the authorization code:"); System.out.println(" " + url); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String code = br.readLine(); GoogleTokenResponse response = flow.newTokenRequest(code).setRedirectUri(REDIRECT_URI).execute(); GoogleCredential credential = new GoogleCredential().setFromTokenResponse(response); java.io.File fileContent = new java.io.File("document.txt"); saveToGoogleDrive(credential, fileContent); } private static final GsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance(); /** Global instance of the HTTP transport. */ private static HttpTransport httpTransport; private static final Log log = LogFactory.getLog(Insert.class); static { try { // initialize the transport httpTransport = GoogleNetHttpTransport.newTrustedTransport(); } catch (IOException ex) { log.error(null, ex); } catch (GeneralSecurityException ex) { log.error(null, ex); } } } 

2016年1月1日更新

这个问题似乎消失了。 我猜Google Drive团队已修复它。

注意:请不要将此视为“Google的官方回答”。 虽然我在Google工作,但我不使用Drive API。

我已经重现了这个问题,并将其报告给Drive API团队,后者可能会提供更多详细信息。 与此同时,我发现的一个解决方法是删除

 setNewRevision(false) 

第1414行的update调用的一部分。这不是一个理想的解决方法,因为这意味着您将获得每个更新的新修订,这将耗尽存储配额。 但是,它确实似乎避免了你所看到的问题。