我正在制作一个通过http。
下载文件的程序我已经下载了,但是我希望能够暂停下载,关闭程序并在以后再次恢复它们。
我知道我正在下载它们的位置支持这个。
我正在通过HttpWebResponse下载文件,并使用GetResponseStream将响应读入流中。
当我关闭应用程序并重新启动它时,我对如何恢复下载感到困惑。我已尝试在流上进行搜索,但声明它不受支持。
最好的方法是什么?
答案 0 :(得分:9)
如果服务器支持此功能,您必须使用Range方法向您的请求发送AddRange Http标头:
request.AddRange(1024);
这将指示服务器在第1千字节后开始发送文件。然后正常阅读响应流。
要测试服务器是否支持恢复,您可以发送HEAD
请求并测试它是否发送Accept-Ranges: bytes
标头。
答案 1 :(得分:2)
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();
}
}
}
答案 2 :(得分:0)
您的解决方案很好,但它仅适用于服务器发送Content-Length标头的情况。此标头不会出现在动态生成的内容中。
此外,此解决方案是发送每个Read的请求。如果内容在请求之间在服务器上发生更改,那么您将得到不一致的结果。
我会通过在本地存储数据来改进这一点 - 无论是在磁盘上还是在内存中。然后,你可以随心所欲地寻找它。不存在任何不一致的问题,您只需要一个HttpWebRequest来下载它。