我有一个 Android 应用程序,可以使用服务帐户复制电子表格、编辑电子表格并将一些照片上传到第三方 Google 云端硬盘帐户。
该应用程序运行正常。但 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 配额和云端硬盘存储配额,它们远低于限制。
我没有更改代码,也没有更改任何相关帐户的安全设置。
我找不到任何与此相关的已知问题。
还有人遇到类似的事情吗?
最佳答案
我找到了问题和候选解决方案。
这是场景:
- 可以访问 Google 云端硬盘的帐户,我们称之为: [email protected] 。
- 几个用于将照片上传到管理器 Google Drive 的帐户,使用 Android 应用程序,我们称之为: [email protected] 。
- 我不想授予访问 [email protected] 的权限 到 [email protected] 的 Google 云端硬盘,所以我创建了一个服务帐户,它负责将照片从Android App上传到管理器Google Drive,我们称之为 [email protected] 。
当 [email protected] 拍照, [email protected] 将照片上传到 [email protected] 谷歌云端硬盘。但照片的所有者是 [email protected] 。所以在 [email protected] Google 云端硬盘,您可以看到所有照片,但配额始终保持为零。
上传 15 GB o 照片后,我实际上超出了配额,但这是 [email protected] 的配额。 (在 Google 云端硬盘中不可见)。
解决方案
登录 [email protected] Google 云端硬盘并删除照片。
ERROR: [email protected] is not the owner. So if you remove the file, it will not be visible to the manager but it will keep on consuming quota of the [email protected].
登录 [email protected] Google 云端硬盘并删除照片。
ERROR: There is no way (AKAIK) to log into a [email protected] Google Drive.
从 [email protected] 转移文件的所有权 至 [email protected] 。
COOL That's a valid solution. Let's do it!!
ERROR It seems that Google does not allow to change the ownership of some types of files. More info here
肮脏的解决方案
是的,这可能不是最优雅的解决方案。但这对我有用。
我使用 [email protected] 创建了一个 Google 脚本 帐户,并且我发布为公共(public) 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 *<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="65160017130c0600250208040c094b060a08" rel="noreferrer noopener nofollow">[email protected]</a>*
DriveApp.removeFile(file);
return ContentService.createTextOutput(JSON.stringify(result)).setMimeType(ContentService.MimeType.JSON);
}
此方法接收由 [email protected] 创建的 fileId ,制作一个副本(拥有 [email protected] )。我需要删除 [email protected] 创建的文件。该文件实际上并未被删除,但它不再链接到 [email protected] 创建的文件。 。最后返回新的 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 *<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="3d505c535c5a584f7d5a505c5451135e5250" rel="noreferrer noopener nofollow">[email protected]</a>*
String ownedPhotoId = makeCopyOfPhoto(photoId);
if(ownedPhotoId != null)
//Once I have copied the photo, I remove the photo owned by *<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="710214030718121431161c10181d5f121e1c" rel="noreferrer noopener nofollow">[email protected]</a>*
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;
}
}
肮脏的解决方案有效,但非常肮脏。我想不出其他方法来解决这个问题。
关于google-drive-api - 使用服务帐户在 Android 上执行 com.google.api.services.drive.Drive.Files.Insert 时出现 403quotaExceeded 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28204149/