【问题标题】:This stream does not support seek operations. HttpWebResponse此流不支持查找操作。 HttpWebResponse
【发布时间】:2009-09-17 19:55:43
【问题描述】:

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

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

我知道我从中下载它们的位置支持这一点。

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

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

最好的方法是什么?

【问题讨论】:

  • 请记住,您必须告诉服务器重新启动 - 您不能自己做。这就是下面AddRange 答案的原因。

标签: c# download httpwebrequest stream httpwebresponse


【解决方案1】:

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

request.AddRange(1024);

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

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

【讨论】:

【解决方案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();
        }

    }
}

【讨论】:

  • 即使服务器不接受恢复,这个类也能工作吗?
  • 我不知道什么是“恢复”。 HTTP 1.1 定义了这个类所依赖的 Range 标头。如果服务器执行 HTTP 1.1,那么它执行 Range,并且可以被此类联系。
  • resuming 我的意思是range header,感谢您的澄清
【解决方案3】:

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

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

我会改进这一点,将数据存储在本地 - 无论是在磁盘上还是在内存中。然后,您可以随心所欲地探索它。不会有不一致的问题,只需要一个HttpWebRequest即可下载。

【讨论】:

    猜你喜欢
    • 2014-06-30
    • 1970-01-01
    • 2011-03-26
    • 1970-01-01
    • 2011-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多