使用服务帐户在Android上执行com.google.api.services.drive.Drive.Files.Insert时出现403 quotaExceeded错误

时间:2015-01-28 23:07:39

标签: google-drive-api http-status-code-403 quota

我有一个Android应用程序,它使用服务帐户复制电子表格,编辑电子表格并将一些照片上传到第三人Google Drive帐户。

该应用程序正常运行。但是,1月的最后一个22,应用程序开始失败。

现在它复制电子表格并进行编辑,但不再上传照片。 我收到了这个错误。

com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden

{re 
  "code" : 403,
  "errors" : [ {
    "domain" : "usageLimits",
    "message" : "The user has exceeded their Drive storage quota",
    "reason" : "quotaExceeded"
  } ],
  "message" : "The user has exceeded their Drive storage quota"
}

我已检查了API配额和云端硬盘存储空间配额,但它们远低于限制。

我没有对代码进行更改,也没有更改任何相关帐户中的安全设置。

我找不到任何已知问题。

是否还有其他人遇到过类似事情?

1 个答案:

答案 0 :(得分:0)

我发现了问题和候选解决方案。

这是情景:

  • 有权访问Google云端硬盘的帐户,我们可以将其命名为: manager@gmail.com
  • 使用Android应用程序将照片上传到经理Google云端硬盘的几个帐户,我们可以将其称为: worker@gmail.com
  • 我不想让 workers@gmail.com 访问 manager@gmail.com 的Google云端硬盘,所以我创建了一个服务帐户,负责将照片从Android应用上传到经理Google云端硬盘,我们将其称为 service@gmail.com

worker@gmail.com 拍照时, service@gmail.com 会将照片上传到 manager@gmail.com Google云端硬盘。但照片的所有者是 service@gmail.com 。因此,在 manager@gmail.com Google云端硬盘中,您可以看到所有照片,但配额始终保持为零。

上传15 GB照片后,我实际上超出了配额,但这是 service@gmail.com 的配额(在Google云端硬盘中不可见)。

<强>解

  1. 登录 manager@gmail.com Google云端硬盘并删除照片。

      

    错误: manager@gmail.com 不是所有者。因此,如果您删除该文件,经理将无法看到该文件,但它会继续消耗 service@gmail.com 的配额。

  2. 登录 service@gmail.com Google云端硬盘并删除照片。

      

    错误:无法登录 service@gmail.com Google云端硬盘。

  3. 将文件的所有权从 service@gmail.com 转移到 manager@gmail.com

      

    COOL 这是一个有效的解决方案。我们来做吧!!

         

    错误 Google似乎不允许更改某些类型文件的所有权。 More info here

  4. DIRTY SOLUTION

    是的,这可能不是最优雅的解决方案。但它对我有用。

    我使用 manager@gmail.com 帐户创建了一个Google脚本,并将其作为公共Web应用程序发布。

    function doGet(data) {
      var fileId = data.parameter.fileId;
      var file = DriveApp.getFileById(fileId);
      var result = { fileId: file.makeCopy(file.getName()).getId() };
      //I need to remove the file. Otherwise it semains linked to the one created by the *service@gmail.com*
      DriveApp.removeFile(file);
      return ContentService.createTextOutput(JSON.stringify(result)).setMimeType(ContentService.MimeType.JSON);
    }
    

    此方法接收 service@gmail.com 创建的fileId,制作副本(拥有 manager@gmail.com )。我需要删除 service@gmail.com 创建的文件。该文件实际上未被删除,但它不再链接到 manager@gmail.com 创建的文件。最后它返回新的fileId。

    现在,我的Android应用程序看起来像这样:

    private void uploadPhoto(String photoFolderId, File body, FileContent mediaContent) {
        //First, I upload the photo
        if(driveService.files().insert(body, mediaContent) != null) {
            transferOwnerShip(photoFolderId);
        }
    
        private void transferOwnerShip(String photoFolderId) {
            String photoId = getInsertedPhotoId();
            //Now I create a copy of the photo. The copied photo is owned by *manager@gmail.com*
            String ownedPhotoId = makeCopyOfPhoto(photoId);
            if(ownedPhotoId != null)
                //Once I have copied the photo, I remove the photo owned by *service@gmail.com*
                driveService.files().delete(photoId).execute();
        }
    
        private String makeCopyOfFile(String fileId) {
            URL url;
            try {
                url = new URL(URL_TO_MY_PUBLIC_SERVICE + "?fileId=" + fileId);
    
                DefaultHttpClient client = new DefaultHttpClient();
                HttpGet get = new HttpGet(url.toURI());
                HttpResponse resp = client.execute(get);
                BufferedReader rd = new BufferedReader(new InputStreamReader(resp.getEntity().getContent()));
                StringBuffer result = new StringBuffer();
                String line = "";
                while ((line = rd.readLine()) != null) {
                    result.append(line);
                }
                JSONObject jsonResponse = new JSONObject(result.toString());
                return jsonResponse.getString("fileId");
            } catch (Exception e) {
                warnAboutError();
            }
            return null;
        }
    
    }
    

    脏解决方案有效,但非常脏。我无法找到解决这个问题的其他方法。