在.NET中如何支持断点续传下载大文件?

27

如何在我的应用程序中从HTTP下载一个大文件(~ 500MB)?我希望支持自动恢复/重试,以便在连接断开时,我的应用程序可以尝试重新连接以获取文件,并避免重新下载已下载的部分(如果可能的话)。 (我知道,这也取决于服务器。)

这类似于下载管理器和一些浏览器的行为。


你需要知道的是,下载是否可以恢复取决于服务器。 - Ranhiru Jude Cooray
@RanhiruCooray 是的,我知道。我的问题是当服务器允许时如何恢复。 - Louis Rhys
你必须自己请求正确的范围。即使是新的闪亮的 Http.Client 也不会自动执行此操作:http://blogs.msdn.com/b/webdev/archive/2012/11/23/asp-net-web-api-and-http-byte-range-support.aspx(除非你找到一个专门的文件下载库)。 - millimoose
@millimoose,也许我误解了什么,但似乎这个链接是关于在服务器中提供简历功能的? - Louis Rhys
1
@LouisRhys 它描述了协议的两个方面,每一方都必须意识到。例如,您发出一个“范围”请求,然后要么得到您想要的范围的“内容范围”响应,要么得到包含整个资源的“正常”响应。无论如何,这只是一个概述,您还需要查看HTTP规范或其他相关文章。 - millimoose
2个回答

15

你可以用以下两种方法之一从头开始实现在 C# 中从web服务器下载:

  1. 使用System.Net中的高级API,例如HttpWebRequestHttpWebResponseFtpWebRequest和其他类。

  2. 使用System.Net.Sockets中的低级API,例如TcpClientTcpListener和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();        

在上述代码的末尾,您将获得一个网络流对象,可以使用它像读取任何其他流对象一样读取远程文件的字节。现在,是否支持从任意位置读取以恢复部分下载取决于如上所示的"Accept-Ranges" HTTP头信息。如果此值设置为除"bytes"以外的任何值,则不支持此功能。

实际上,这段代码是我试图用C#实现的一个更大的开源下载管理器的一部分。您可以参考此应用程序,并查看是否有任何可帮助您的内容:http://scavenger.codeplex.com/


3

5
不要只在回答中附上链接,而是加入一些文字说明,说明这个答案如何帮助OP解决当前的问题。谢谢。 - ρяσѕρєя K
@leonidp 一切看起来都很好,但是缺少一个名为DownloadCacheImplementation的类。你能帮我解决一下吗? - user240141
1
@AmitRanjan 这里是一个非常简单的DownloadCache实现,它将文件存储在临时文件夹中,并使用ETag来检测文件是否被修改:http://pastebin.com/GY7fRER0。你可能需要稍微调整一下,因为我没有很好地测试它。 - leonid p
5
这个链接显示页面未找到,错误代码为404。 - R.Akhlaghi
可能是这个 https://github.com/captincook/.NetFileDownloader - Roman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接