Не удается выполнить экспорт файла Google Drive API в конечной точке при аутентификации по ключу API?

Что-нибудь изменилось в последнее время с API Google Drive и, в частности, с функцией " Экспорт", что может привести к сбою при использовании доступа к API-ключу после 27 марта 2018 года?

У меня есть служба Windows, которая создает и отправляет ежедневные электронные письма о курсе для образовательной группы. Исходный контент для каждого электронного письма хранится на Google Диске, как Google Doc, так что преподаватели могут легко обновлять содержание курса.

Это работало безупречно в течение прошлого года, но внезапно перестало работать около 27 марта 2018 года. С тех пор я могу получить информацию о файле;

    _googleDriveHtmlContent.LoadFile(
        fileId
        );

Но не содержание. Когда я Export файл в формате HTML, я сразу получаю DownloadStatus.Failed от ProgressChanged обработчик;

    var request = _driveService.Files.Export(
        fileId, 
        "text/html"
        );

Я использую ключи API для безопасности, а не OAuth, поскольку это сервис без пользовательского интерфейса. Для этого мне нужно пометить папки с файлами как общедоступные - в частности, я использую "Доступно для всех со ссылкой". Это работает отлично.

Я обновил до последних библиотек API v3 через NuGet, без изменений в поведении.

Используя Google Explorer Explorer, я вижу похожее поведение.

Я могу получить свой файл успешно, используя API Explorer с get конечная точка. https://developers.google.com/drive/v3/reference/files/get

  • FILEID 1AIuGhzXsNuhhi0PMA1pblh0l5CCDaa1nPj8t_dasi_c
  • Аутентификация: ключ API (используется "демонстрационный ключ API")

Но с export конечная точка, я получаю внутреннюю ошибку (500)- https://developers.google.com/drive/v3/reference/files/export

  • FILEID 1AIuGhzXsNuhhi0PMA1pblh0l5CCDaa1nPj8t_dasi_c
  • MIMETYPE: text/html
  • Аутентификация: ключ API (используется "демонстрационный ключ API")

Изменив Аутентификацию в API Explorer на OAuth 2.0 и подтвердив доступ, вы получите успешный результат 200 с файлом HTML. Однако я не могу этого сделать, так как я получаю доступ к API через сервис без пользовательского интерфейса.

1 ответ

Решение

Что-нибудь изменилось в последнее время с API Google Drive и, в частности, с функцией "Экспорт", что может привести к сбою при использовании доступа к API-ключу после 27 марта 2018 года?

Это возможно, но, скорее всего, это скрытое изменение, о котором вы не получите никакого официального слова. Не так давно я видел, как кто-то отправлял похожий вопрос, он использовал API-ключ для обновления листа Google, и он внезапно перестал работать.

ИМО, если Google изменил это, вероятно, это хорошая вещь. Ключи API предназначены для доступа к публичным данным. Установка публичного документа - это действительно плохая идея, если кому-то удастся найти идентификатор файла вашего документа, то он сможет обновить ваш документ.

Предложение:

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

Вы не указали, какой язык вы используете, но вы сказали, что делаете службу Windows, поэтому я предполагаю, что вы используете.net. Вот пример аутентификации учетной записи службы с помощью клиентской библиотеки Google .net.

 public static DriveService AuthenticateServiceAccount(string serviceAccountEmail, string serviceAccountCredentialFilePath, string[] scopes)
    {
        try
        {
            if (string.IsNullOrEmpty(serviceAccountCredentialFilePath))
                throw new Exception("Path to the service account credentials file is required.");
            if (!File.Exists(serviceAccountCredentialFilePath))
                throw new Exception("The service account credentials file does not exist at: " + serviceAccountCredentialFilePath);
            if (string.IsNullOrEmpty(serviceAccountEmail))
                throw new Exception("ServiceAccountEmail is required.");                

            // For Json file
            if (Path.GetExtension(serviceAccountCredentialFilePath).ToLower() == ".json")
            {
                GoogleCredential credential;
                using (var stream = new FileStream(serviceAccountCredentialFilePath, FileMode.Open, FileAccess.Read))
                {
                    credential = GoogleCredential.FromStream(stream)
                         .CreateScoped(scopes);
                }

                // Create the  Analytics service.
                return new DriveService(new BaseClientService.Initializer()
                {
                    HttpClientInitializer = credential,
                    ApplicationName = "Drive Service account Authentication Sample",
                });
            }
            else if (Path.GetExtension(serviceAccountCredentialFilePath).ToLower() == ".p12")
            {   // If its a P12 file

                var certificate = new X509Certificate2(serviceAccountCredentialFilePath, "notasecret", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
                var credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(serviceAccountEmail)
                {
                    Scopes = scopes
                }.FromCertificate(certificate));

                // Create the  Drive service.
                return new DriveService(new BaseClientService.Initializer()
                {
                    HttpClientInitializer = credential,
                    ApplicationName = "Drive Authentication Sample",
                });
            }
            else
            {
                throw new Exception("Unsupported Service accounts credentials.");
            }

        }
        catch (Exception ex)
        {                
            throw new Exception("CreateServiceAccountDriveFailed", ex);
        }
    }
}

Код скопирован из serviceaccount.cs. Предполагая, что вы уже использовали клиентскую библиотеку Google .net, сервис, который возвращает этот метод, будет тем же сервисом дисков, который вы использовали с ключом API.

После того как вы предоставили доступ к файлу своей учетной записи службы, он сможет получить доступ к файлу, когда в этом будет необходимость, аутентификация не требуется, поскольку вы предварительно авторизовали его, предоставив ему доступ к файлу.

Другие вопросы по тегам