使用Google Drive .NET API上载文件时,有时会出现空ResponseBody

问题描述 投票:0回答:2

当我将某些文件发送到Google驱动器时,有时有时会得到空的ResponseBody。

这是随机发生的,大多数文件都已发送,但是十分之一的文件返回空的ResponseBody。

我搜索了此内容,但是仅存在有关距离为herehere的响应为空的问题

我的代码:

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?为何只发生几次?

更新:

我编辑UploadFileAsync(),以检查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;
            });
        }

有人可以帮我吗?

c# .net google-drive-api google-api-dotnet-client
2个回答
1
投票

您正在获取500 Error Code,因为这是与exponential backoff相关的问题。由于您要发出的并发请求数量众多,因此会发生这种情况。

因此,在您的代码中,您将需要应用一些逻辑来避免该问题。例如[algorithm

如果请求失败,请等待1 + random_number_milliseconds秒,然后重试请求。

如果请求失败,请等待2 + random_number_milliseconds秒,然后重试请求。

如果请求失败,请等待4 + random_number_milliseconds秒,然后重试请求。

依此类推,直到最大退避时间。

其中:

等待时间为min((((2 ^ n)+ random_number_milliseconds),maximum_backoff),每次迭代n都会增加1(请求)。

random_number_milliseconds是随机的毫秒数大于或等于1000。这有助于避免出现许多客户的情况在某些情况下同步并立即重试,发送同步波浪中的请求。的价值每个重试请求后都会重新计算random_number_milliseconds。

maximum_backoff通常为32或64秒。适当的值取决于用例。


0
投票

基于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;
            });
    }

© www.soinside.com 2019 - 2024. All rights reserved.