mat*_*att 13 .net c# rest google-drive-api
我目前正在开发一个网络连接不佳的环境.我的应用有助于为用户自动下载所需的Google云端硬盘文件.它适用于小文件(范围从40KB到2MB),但对于较大的文件(9MB)则经常失败.我知道这些文件大小可能看起来很小,但就我客户的网络环境而言,Google Drive API始终会因9MB文件而失败.
我已经得出结论,我需要以较小的字节块下载文件,但我不知道如何使用Google Drive API来实现这一点.我一遍又一遍地阅读这篇文章,我尝试了以下代码:
// with the Drive File ID, and the appropriate export MIME type, I create the export request
var request = DriveService.Files.Export(fileId, exportMimeType);
// take the message so I can modify it by hand
var message = request.CreateRequest();
var client = request.Service.HttpClient;
// I change the Range headers of both the client, and message
client.DefaultRequestHeaders.Range =
message.Headers.Range =
new System.Net.Http.Headers.RangeHeaderValue(100, 200);
var response = await request.Service.HttpClient.SendAsync(message);
// if status code = 200, copy to local file
if (response.IsSuccessStatusCode)
{
using (var fileStream = new FileStream(downloadFileName, FileMode.CreateNew, FileAccess.ReadWrite))
{
await response.Content.CopyToAsync(fileStream);
}
}
Run Code Online (Sandbox Code Playgroud)
fileStream但是,生成的本地文件(来自)仍然是全长的(即40KB驱动器文件为40KB文件,9MB文件为500内部服务器错误).在旁注中,我也进行了实验ExportRequest.MediaDownloader.ChunkSize,但从我观察到它只会改变ExportRequest.MediaDownloader.ProgressChanged调用回调的频率(即如果ChunkSize设置为256*1024,则回调将触发每256KB ).
我该怎么办?
你似乎朝着正确的方向前进.根据您的上一条评论,请求将根据块大小更新进度,因此您的观察结果是准确的.
查看SDK中的源代码,MediaDownloader发现以下内容(强调我的)
核心下载逻辑.我们下载媒体并一次将其写入输出流ChunkSize字节,在每个块之后引发ProgressChanged事件.分块行为主要是历史工件:先前的实现发出多个Web请求,每个请求用于ChunkSize字节.现在我们在一个请求中执行所有操作,但保留API和客户端可见行为以保持兼容性.
您的示例代码只会从100到200下载一个块.使用该方法,您必须跟踪索引并手动下载每个块,将它们复制到文件流中以进行每个部分下载
const int KB = 0x400;
int ChunkSize = 256 * KB; // 256KB;
public async Task ExportFileAsync(string downloadFileName, string fileId, string exportMimeType) {
var exportRequest = driveService.Files.Export(fileId, exportMimeType);
var client = exportRequest.Service.HttpClient;
//you would need to know the file size
var size = await GetFileSize(fileId);
using (var file = new FileStream(downloadFileName, FileMode.CreateNew, FileAccess.ReadWrite)) {
file.SetLength(size);
var chunks = (size / ChunkSize) + 1;
for (long index = 0; index < chunks; index++) {
var request = exportRequest.CreateRequest();
var from = index * ChunkSize;
var to = from + ChunkSize - 1;
request.Headers.Range = new RangeHeaderValue(from, to);
var response = await client.SendAsync(request);
if (response.StatusCode == HttpStatusCode.PartialContent || response.IsSuccessStatusCode) {
using (var stream = await response.Content.ReadAsStreamAsync()) {
file.Seek(from, SeekOrigin.Begin);
await stream.CopyToAsync(file);
}
}
}
}
}
private async Task<long> GetFileSize(string fileId) {
var file = await driveService.Files.Get(fileId).ExecuteAsync();
var size = file.size;
return size;
}
Run Code Online (Sandbox Code Playgroud)
此代码对驱动器api/server进行了一些假设.
Range开发人员文档中所述的标头| 归档时间: |
|
| 查看次数: |
1312 次 |
| 最近记录: |