Null ResponseBody иногда при загрузке файла с помощью Google Drive. NET API - PullRequest
0 голосов
/ 17 марта 2020

Иногда я получаю нулевое значение ResponseBody при отправке некоторых файлов на диск Google.

Это происходит случайным образом, большинство файлов отправляются, но 1 из 10 файлов возвращает нулевое значение ResponseBody.

Я искал это, но есть только вопросы о том, чтобы получить ответ null здесь и здесь

Мой код:

await UploadFileAsync(...); //exception here

public Task<string> UploadFileAsync(DriveService driveService, string LocalPath, string gdriveFileName, string GDriveFolder, IProgress<long> progress)
{
            return Task.Run(() =>
            {
                var folderId = GetDirectoryOrCreateIfNotExist(driveService, GDriveFolder);
                var file = CreateGDriveFile(gdriveFileName, folderId);

                IUploadProgress result = null;
                FilesResource.CreateMediaUpload request;
                using (var stream = new System.IO.FileStream(LocalPath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                {
                    request = driveService.Files.Create(file, stream, "image/jpeg");
                    request.ChunkSize = ResumableUpload.MinimumChunkSize * 4;

                    request.ProgressChanged += (p) => progress.Report(p.BytesSent * 100 / stream.Length);

                    request.Fields = "id, webContentLink, name";
                    result = request.Upload();
                }

                if (request == null)
                    throw new Exception("O request é nulo");

                if (request.ResponseBody == null)
                    throw new Exception("O ResponseBody é nulo"); //Throw here sometimes

                var fileUploaded = request.ResponseBody;

                return fileUploaded.WebContentLink;
            });
}

private string GetDirectoryOrCreateIfNotExist(DriveService driveService, string folderName)
        {
            var folder = GetFolderIdByName(driveService, folderName).FirstOrDefault();

            if (folder == null)
            {
                folder = CreateGDriveDirectory(driveService, folderName);
                AplyPermissionToFile(driveService, folder);
            }

            return folder;
        }

private File CreateGDriveFile(string fileName, string folderName = null)
        {
            var file = new File()
            {
                Name = fileName
            };

            if (folderName != null)
            {
                file.Parents = new List<string>
                {
                    folderName
                };
            }

            return file;
        }

Почему ResponseBody имеет значение null? и Почему это происходит только несколько раз?

Обновление:

Я редактирую UploadFileAsyn c (), чтобы проверить UploadStatus, теперь я получаю :

The service drive has thrown an exception: Google.GoogleApiException: Google.Apis.Requests.RequestError
Internal Error [500]
Errors [
    Message[Internal Error] Location[ - ] Reason[internalError] Domain[global]
]

обновленный код: (см. Result.Status! = UploadStatus.Completed)

public Task<string> UploadFileAsync(DriveService driveService, string LocalPath, string gdriveFileName, string GDriveFolder, IProgress<long> progress)
        {
            return Task.Run(() =>
            {
                var folderId = GetDirectoryOrCreateIfNotExist(driveService, GDriveFolder);
                var file = CreateGDriveFile(gdriveFileName, folderId);

                IUploadProgress result = null;
                FilesResource.CreateMediaUpload request;
                using (var stream = new System.IO.FileStream(LocalPath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                {
                    request = driveService.Files.Create(file, stream, "image/jpeg");
                    request.ChunkSize = ResumableUpload.MinimumChunkSize * 4;

                    request.ProgressChanged += (p) => progress.Report(p.BytesSent * 100 / stream.Length);

                    request.Fields = "id, webContentLink, name";
                    result = request.Upload();
                }

                if (result.Status != UploadStatus.Completed) //check status, now it's throwing here sometimes
                    throw result.Exception;

                if (request == null)
                    throw new Exception("O request é nulo");

                if (request.ResponseBody == null)
                    throw new Exception("O ResponseBody é nulo");

                var fileUploaded = request.ResponseBody;

                return fileUploaded.WebContentLink;
            });
        }

Может кто-нибудь мне помочь?

Ответы [ 2 ]

1 голос
/ 17 марта 2020

Исходя из ответа alberto vielma , мой код теперь работает и выглядит следующим образом:

    public Task<string> UploadFileAsync(DriveService driveService, string LocalPath, string gdriveFileName, string GDriveFolder, IProgress<long> progress)
    {
            return Task.Run(() =>
            {
                var folderId = GetDirectoryOrCreateIfNotExist(driveService, GDriveFolder);
                var file = CreateGDriveFile(gdriveFileName, folderId);

                IUploadProgress result = null;
                FilesResource.CreateMediaUpload request;
                using (var stream = new System.IO.FileStream(LocalPath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                {
                    request = driveService.Files.Create(file, stream, "image/jpeg");
                    request.ChunkSize = ResumableUpload.MinimumChunkSize * 4;

                    request.ProgressChanged += (p) => progress.Report(p.BytesSent * 100 / stream.Length);

                    request.Fields = "id, webContentLink, name";
                    result = request.Upload();

                    //solution: Truncated exponential backoff
                    if (result.Status != UploadStatus.Completed)
                    {
                        var rdn = new Random();
                        var waitTime = 0;
                        var count = 0;
                        do
                        {
                            waitTime = (Convert.ToInt32(Math.Pow(2, count)) * 1000) + rdn.Next(0, 1000);
                            Thread.Sleep(waitTime);

                            result = request.Upload();
                            count++;

                        } while (count < 5 && (result.Status != UploadStatus.Completed));
                    }//end solution
                }

                if (result.Status != UploadStatus.Completed)
                    throw result.Exception; //Doesn't get here anymore

                var fileUploaded = request.ResponseBody;

                return fileUploaded.WebContentLink;
            });
    }

1 голос
/ 17 марта 2020

Вы получаете этот 500 код ошибки , потому что это проблема, связанная с экспоненциальным откатом . Это произойдет из-за количества одновременных запросов, которые вы пытаетесь сделать.

Следовательно, в вашем коде вам потребуется применить некоторые логики c, чтобы избежать этой проблемы. Как, например, этот алгоритм :

Если запрос не выполнен, подождите 1 + random_number_milliseconds секунд и повторите запрос.

Если запрос не выполнен, подождите 2 + random_number_milliseconds секунд и повторите запрос.

Если запрос не выполнен, подождите 4 + random_number_milliseconds секунд и повторите запрос.

И так далее, вплоть до максимального времени отката.

где:

Время ожидания составляет мин (((2 ^ n) + random_number_milliseconds), Maximum_backoff), причем n увеличивается на 1 для каждой итерации (запроса).

random_number_milliseconds является случайным числом в миллисекундах, меньших или равных 1000. Это помогает избежать случаев, когда многие клиенты синхронизируются в определенной ситуации и все повторяются одновременно, отправляя запросы синхронизированными волнами. Значение random_number_milliseconds пересчитывается после каждого запроса на повторную попытку.

Maximum_backoff обычно составляет 32 или 64 секунды. Соответствующее значение зависит от варианта использования.

...