从 HTTP 下载大文件并在 .NET 中支持恢复/重试?
Posted
技术标签:
【中文标题】从 HTTP 下载大文件并在 .NET 中支持恢复/重试?【英文标题】:Download large file from HTTP with resume/retry support in .NET? 【发布时间】:2013-04-22 14:55:09 【问题描述】:如何在我的应用程序中实现从 HTTP 下载大文件(~500MB)?我想支持自动恢复/重试,这样当连接断开时,我的应用程序可以尝试重新连接以获取文件并避免重新下载下载的部分,如果可能的话(我知道,这也取决于服务器)。
这类似于下载管理器和某些浏览器中的行为。
【问题讨论】:
你应该知道的是,是否可以恢复下载是由服务器决定的 @RanhiruCooray 是的,我知道这一点。我的问题是如何在服务器允许时恢复 您必须自己请求正确的范围。甚至新的闪亮Http.Client
也不会自动执行此操作:blogs.msdn.com/b/webdev/archive/2012/11/23/…(除非您找到专用的文件下载库。)
@millimoose 也许我误解了什么,但似乎该链接是关于在服务器中提供恢复功能的?
@LouisRhys 它描述了协议的双方,任何一方都必须意识到这一点。 IE。你发出一个Range
请求,然后得到你想要的范围的Content-Range
响应,或者你得到一个包含整个资源的“正常”响应。无论如何,这只是一个概述,您还必须查看 HTTP 规范或有关该主题的其他文章。
【参考方案1】:
您可以通过以下两种方式之一从C#
中的网络服务器实现下载:
使用 System.Net 中的高级 API,例如 HttpWebRequest
、HttpWebResponse
、FtpWebRequest
和其他类。
使用 System.Net.Sockets 中的低级 API,例如 TcpClient
、TcpListener
和 Socket 类。
使用第一种方法的优点是您通常不必担心低级管道,例如准备和解释 HTTP 标头以及处理代理、身份验证、缓存等。高级类为你,因此我更喜欢这种方法。
使用第一种方法,准备从 url 下载文件的 HTTP 请求的典型代码如下所示:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
if (UseProxy)
request.Proxy = new WebProxy(ProxyServer + ":" + ProxyPort.ToString());
if (ProxyUsername.Length > 0)
request.Proxy.Credentials = new NetworkCredential(ProxyUsername, ProxyPassword);
//HttpWebRequest hrequest = (HttpWebRequest)request;
//hrequest.AddRange(BytesRead); ::TODO: Work on this
if (BytesRead > 0) request.AddRange(BytesRead);
WebResponse response = request.GetResponse();
//result.MimeType = res.ContentType;
//result.LastModified = response.LastModified;
if (!resuming)//(Size == 0)
//resuming = false;
Size = (int)response.ContentLength;
SizeInKB = (int)Size / 1024;
acceptRanges = String.Compare(response.Headers["Accept-Ranges"], "bytes", true) == 0;
//create network stream
ns = response.GetResponseStream();
在上述代码的末尾,您会得到一个网络流对象,然后您可以使用它来读取远程文件的字节,就像您正在读取任何其他流对象一样。现在,远程 url 是否支持通过允许您从任意位置读取来恢复部分下载由 "Accept-Ranges" HTTP 标头决定,如上所示。如果此值设置为“字节”以外的任何值,则不支持此功能。
事实上,这段代码是我试图在 C# 中实现的更大的开源下载管理器的一部分。你可以参考这个应用程序,看看有没有什么对你有帮助:http://scavenger.codeplex.com/
【讨论】:
【参考方案2】:有一个开源的.Net http文件下载器,支持自动恢复/重试(如果服务器支持的话),看起来正是你需要的,可以尝试使用它:
https://github.com/Avira/.NetFileDownloader.
【讨论】:
不要将链接发布为答案,而是添加一些文本来解释此答案如何帮助 OP 解决当前问题。谢谢 @leonidp 那里看起来一切都很好,但是缺少一个类 DownloadCacheImplementation。你能帮帮我吗? @AmitRanjan 这里是非常简单的 DownloadCache 实现,它将文件存储在临时文件夹中,并使用 ETag 来检测文件是否被修改:pastebin.com/GY7fRER0。你可能需要稍微调整一下,因为我没有很好地测试它。 此链接显示页面未找到 404以上是关于从 HTTP 下载大文件并在 .NET 中支持恢复/重试?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Ktor HTTP 客户端(和 kotlinx.io?)直接将可恢复下载到文件
使用动态 url 暂停和恢复从 CDN(内容分发网络)下载大文件