Проблема с загрузкой файлов из GDrive с помощью Google API для .NET

#c# #google-api #google-drive-api #google-api-dotnet-client

#c# #google-api #google-drive-api #google-api-dotnet-client

Вопрос:

Уже несколько лет у меня есть приложение, с помощью которого пользователи могут загружать данные из GDrive. Данные могут быть из собственных электронных таблиц Google (GSheets) или файлов типа txt, csv, xlsx. Внезапно, однако, с некоторых пор на этой неделе файлы больше не могут быть загружены, хотя с нашей стороны ничего не изменилось. Когда я пытаюсь загрузить файл, я получаю содержимое html-страницы, которая в основном является экраном входа в систему. Однако содержимое GSheets все еще можно загрузить, поэтому это не может быть связано с некоторыми проблемами доступа к учетной записи службы, которую я использую. Я также могу подтвердить, что файлы по-прежнему доступны для этой учетной записи службы. Я использую этот код для загрузки файлов:

         String serviceAccountEmail = this.apiConfig.ClientIdEmail;
        Byte[] keyFile = this.apiConfig.FileP12;

        var certificate = new X509Certificate2(keyFile, "notasecret", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);

        ServiceAccountCredential credential = new ServiceAccountCredential(
           new ServiceAccountCredential.Initializer(serviceAccountEmail)
           {
               Scopes = new[] { DriveService.Scope.Drive, DriveService.Scope.DriveFile }
           }.FromCertificate(certificate));

        DriveService service = new DriveService(new BaseClientService.Initializer()
        {
            HttpClientInitializer = credential,
            ApplicationName = "Drive Spotfire Datasource",
        });

        var response = service.HttpClient.GetByteArrayAsync(exportUrl).Resu<
        Stream downloadStream = new MemoryStream(response);
  

«exportUrl» имеет формат

 https://docs.google.com/a/<domain.com>/uc?id=<fileId>amp;export=downloadamp;gid=0
  

и когда я пытаюсь использовать этот URL в браузере, я могу загрузить файл без проблем.
Тем временем я пытался использовать последние библиотеки DLL от NuGet (версия 1.38) для обоих Google.Api.Drive.v2 и Google.Apis.Диск.v3.
У кого-нибудь есть идея, почему эти загрузки внезапно больше не работают?

Комментарии:

1. Похоже, что вы используете HTTP-клиент с аутентификацией учетной записи службы для последующей прямой загрузки. Я знаю, вы утверждаете, что учетная запись службы по-прежнему имеет права доступа к файлам, но наиболее вероятной причиной проблемы является то, что разрешения на файлы изменились, и учетной записи службы больше не разрешено получать доступ к файлам. Это объясняет, почему вы видите HTML-страницу авторизации вместо ожидаемого содержимого файла. Ваш exportURL может работать в браузере, поскольку вы уже вошли в систему в браузере.

2. Привет @Chris, спасибо за твой комментарий. Я проверил в GDrive, что файлы по-прежнему доступны совместно с учетной записью службы. И они это делают, точно так же, как GSheets по-прежнему используются совместно с ним. На самом деле я также создал новую учетную запись службы с новым файлом p12, предоставил общий доступ к файлу в GDrive с этой новой учетной записью, и та же проблема все еще возникает.

3. Только что пробовал с Google.Apis. Диск.v3. Все та же проблема.

Ответ №1:

Тем временем я нашел решение. Оказывается, что при загрузке файлов необходимо использовать другой URL:

     String serviceAccountEmail = this.apiConfig.ClientIdEmail;
    Byte[] keyFile = this.apiConfig.FileP12;

    var certificate = new X509Certificate2(keyFile, "notasecret", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);

    ServiceAccountCredential credential = new ServiceAccountCredential(
       new ServiceAccountCredential.Initializer(serviceAccountEmail)
       {
           Scopes = new[] { DriveService.Scope.Drive, DriveService.Scope.DriveFile }
       }.FromCertificate(certificate));

    DriveService service = new DriveService(new BaseClientService.Initializer()
    {
        HttpClientInitializer = credential,
        ApplicationName = "Drive Spotfire Datasource",
    });

    //get file handler
    Google.Apis.Drive.v2.Data.File file = service.Files.Get(this.uniqueKey).Execute();
    if (!file.MimeType.Equals("application/vnd.google-apps.spreadsheet"))
    {
        //for files use another Url
        exportUrl = file.DownloadUrl;
    }
    var response = service.HttpClient.GetByteArrayAsync(exportUrl).Resu<
    Stream downloadStream = new MemoryStream(response);