Ошибка 403 quotaExceeded при выполнении com.google.api.services.drive.Drive.Files.Insert на Android с использованием сервисной учетной записи

У меня есть приложение для Android, которое копирует электронную таблицу, редактирует электронную таблицу и загружает некоторые фотографии в учетную запись Google Диска третьего лица, используя учетную запись службы.

Приложение работало нормально. Но 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, и квоту хранилища Диска, и они значительно ниже предела.

Я не вносил изменений в код и не менял настройки безопасности ни в одной из задействованных учетных записей.

Я не смог найти ни одной известной проблемы по этому поводу.

Кто-нибудь еще испытывает что-то подобное??


person Oca    schedule 28.01.2015    source источник
comment
Вероятно, дублируется с этим: stackoverflow.com/ вопросы/15860562/   -  person Dayton Wang    schedule 30.01.2015
comment
Я тоже такое недавно сегодня наблюдаю.   -  person TJC    schedule 30.01.2015


Ответы (1)


Я нашел проблему и вариант решения.

Это сценарий:

  • Аккаунт с доступом к Google Диску, назовем его: [email protected].
  • Несколько учетных записей, которые используются для загрузки фотографий в диспетчер Google Диска с помощью приложения для Android, назовем его: [email protected].
  • Я не хочу предоставлять доступ [email protected] к Google Диску [email protected], поэтому я создал сервисный аккаунт, который ответственный за загрузку фотографий из приложения Android на Google Диск менеджера, назовем его [email protected].

Когда [email protected] делает фото, [email protected] загружает фото на [email protected] Google Диск. Но владельцем фотографии является [email protected]. Таким образом, в [email protected] Google Диске вы можете видеть все фотографии, но квота всегда остается равной нулю.

После загрузки 15 ГБ фотографий я фактически превысил квоту, но это была квота [email protected] (которого не видно на Google Диске).

РЕШЕНИЯ

  1. #P6# <блочная цитата> #P7#
  2. #P8# <блочная цитата> #P9#
  3. #P10# <цитата> #P11# #P12#

ГРЯЗНОЕ РЕШЕНИЕ

Да, возможно, это не самое элегантное решение. Но это сработало для меня.

Я создал скрипт Google, используя учетную запись [email protected], и опубликовал его как общедоступное веб-приложение.

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 *[email protected]*
  DriveApp.removeFile(file);
  return ContentService.createTextOutput(JSON.stringify(result)).setMimeType(ContentService.MimeType.JSON);
}

Эти методы получают идентификатор файла, созданный [email protected], и делают копию (которой владеет [email protected]). Мне нужно удалить файл, созданный [email protected]. Файл на самом деле не удаляется, но он больше не связан с файлом, созданным пользователем [email protected]. Наконец, он возвращает новый идентификатор файла.

Теперь мое приложение для 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 *[email protected]*
        String ownedPhotoId = makeCopyOfPhoto(photoId);
        if(ownedPhotoId != null)
            //Once I have copied the photo, I remove the photo owned by *[email protected]*
            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;
    }

}

Грязное решение работает, но оно очень грязное. Я не мог найти другого способа обойти это.

person Oca    schedule 31.01.2015