此流不支持搜索操作。 HttpWebResponse

我正在制作一个通过http下载文件的程序。

我已经下载了,但是我希望能够暂停下载,关闭程序并在以后再次恢复它们。

我知道我从下载它们的位置支持这个。

我正在通过HttpWebResponse下载文件,并使用GetResponseStream将响应读入流中。

当我关闭应用程序并重新启动它时,我不知道如何恢复下载。 我已尝试在流上进行搜索,但它表示不支持。

最好的方法是什么?

如果服务器支持此function,则必须使用AddRange方法将Range Http标头与您的请求一起发送:

 request.AddRange(1024); 

这将指示服务器在第1千字节后开始发送文件。 然后正常读取响应流。

要测试服务器是否支持恢复,您可以发送HEAD请求并测试它是否发送Accept-Ranges: bytes标头。

HTTPRangeStream类怎么样?

 using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Text; namespace Ionic.Kewl { public class HTTPRangeStream : Stream { private string url; private long length; private long position; private long totalBytesRead; private int totalReads; public HTTPRangeStream(string URL) { url = URL; HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url); HttpWebResponse result = (HttpWebResponse)request.GetResponse(); length = result.ContentLength; } public long TotalBytesRead { get { return totalBytesRead; } } public long TotalReads { get { return totalReads; } } public override bool CanRead { get { return true; } } public override bool CanSeek { get { return true; } } public override bool CanWrite { get { return false; } } public override long Length { get { return length; } } public override bool CanTimeout { get { return base.CanTimeout; } } public override long Position { get { return position; } set { if (value < 0) throw new ArgumentException(); position = value; } } public override long Seek(long offset, SeekOrigin origin) { switch (origin) { case SeekOrigin.Begin: position = offset; break; case SeekOrigin.Current: position += offset; break; case SeekOrigin.End: position = Length + offset; break; default: break; } return Position; } public override int Read(byte[] buffer, int offset, int count) { HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url); request.AddRange(Convert.ToInt32(position), Convert.ToInt32(position) + count); HttpWebResponse result = (HttpWebResponse)request.GetResponse(); using (Stream stream = result.GetResponseStream()) { stream.Read(buffer, offset, count); stream.Close(); } totalBytesRead += count; totalReads++; Position += count; return count; } public override void Write(byte[] buffer, int offset, int count) { throw new NotSupportedException(); } public override void SetLength(long value) { throw new NotSupportedException(); } public override void Flush() { throw new NotSupportedException(); } } } 

您的解决方案很好,但它只适用于服务器发送Content-Length标头的情况。 此标头不会出现在动态生成的内容中。

此外,此解决方案是发送每个Read的请求。 如果内容在请求之间在服务器上发生更改,那么您将得到不一致的结果。

我会通过在本地存储数据来改进这一点 – 无论是在磁盘上还是在内存中。 然后,你可以随心所欲地寻找它。 不存在任何不一致的问题,您只需要一个HttpWebRequest来下载它。