#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);