【发布时间】:2021-01-19 03:02:24
【问题描述】:
我在使用 .NET V3 nuGet 包从 Google Drive 下载超过 1.5 GB 的大文件时遇到问题。
使用下面的代码:
public void DownloadFile(string fileId, string saveTo)
{
var request = service.Files.Get(fileId);
var stream = new System.IO.MemoryStream();
// Add a handler which will be notified on progress changes.
// It will notify on each chunk download and when the
// download is completed or failed.
request.MediaDownloader.ProgressChanged += (Google.Apis.Download.IDownloadProgress progress) =>
{
switch (progress.Status)
{
case Google.Apis.Download.DownloadStatus.Downloading:
{
Console.WriteLine(progress.BytesDownloaded);
break;
}
case Google.Apis.Download.DownloadStatus.Completed:
{
Console.WriteLine("Download complete.");
SaveStream(stream, saveTo);
break;
}
case Google.Apis.Download.DownloadStatus.Failed:
{
Console.WriteLine("Download failed.");
break;
}
}
};
request.Download(stream);
GC.Collect();
}
public void SaveStream(System.IO.MemoryStream stream, string saveTo)
{
using (System.IO.FileStream file = new System.IO.FileStream(saveTo, System.IO.FileMode.Create, System.IO.FileAccess.Write))
{
try
{
stream.WriteTo(file);
}
catch(Exception ex)
{
}
}
}
我在 Google.Apis.Download.IDownloadProgress 中遇到异常:
引发了“System.OutOfMemoryException”类型的异常。
堆栈跟踪是:
at System.IO.MemoryStream.set_Capacity(Int32 value)
at System.IO.MemoryStream.EnsureCapacity(Int32 value)
at System.IO.MemoryStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at System.IO.MemoryStream.WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
at Google.Apis.Download.MediaDownloader.<DownloadCoreAsync>d__31.MoveNext()
控制台输出如下所示:
.
.
.
1310720000
1321205760
1331691520
1342177280
Download failed.
就下载的字节数而言,它通常在同一点附近失败。
有没有办法使用部分下载或继续下载?我找不到太多文档或示例。我似乎无法访问 request.MediaDownloader.Range 来设置它。我看不到任何设置范围标题的方法。我尝试过使用块大小,但无济于事。
【问题讨论】:
-
这是一个有趣的问题,我以前没有遇到过。你可能想把它交叉发布到图书馆github.com/googleapis/google-api-dotnet-client/issues
-
这有帮助吗? stackoverflow.com/questions/38449621/… // 在 developers.google.com/api-client-library/dotnet/guide/… 中也有对
progress.BytesDownloaded的引用 - 也许这也有帮助? -
我正在循环上面代码中的 BytesDownloaded。那就是输出。我似乎无法访问 Range 标头。我找不到任何使用 Google API 中的 MediaDownloader 功能分块下载的具体示例。
-
在我链接的堆栈问题中,引用了
var request = exportRequest.CreateRequest(); request.Headers.Range = new RangeHeaderValue(from, to);- 这不起作用吗? -
我停止使用内存流,而是使用文件流,之后代码就可以工作了。我能够显式转换为 MediaDownloader 以获取 Range 值,但在下载 1.2 - 1.3 GB 后它仍然内存不足。所以,我所做的就是将 MemoryStream 切换到 FileStream。我将流写入磁盘而不是缓冲。它给我留下了一个问题,我现在可以在挂起之前直接下载 5 或 6 个文件(每个文件大约 3-4 GB)。这可以通过在每次下载后刷新和关闭 FileStream 来解决。我会正式回答这个问题。
标签: c# google-api google-drive-api