簡體   English   中英

此流不支持搜索操作。 HttpWebResponse

[英]This stream does not support seek operations. HttpWebResponse

我正在制作一個通過http下載文件的程序。

我已經下載了,但是我希望能夠暫停下載,關閉程序並在以后再次恢復它們。

我知道我從下載它們的位置支持這個。

我正在通過HttpWebResponse下載文件,並使用GetResponseStream將響應讀入流中。

當我關閉應用程序並重新啟動它時,我不知道如何恢復下載。 我已嘗試在流上進行搜索,但它聲明它不受支持。

最好的方法是什么?

如果服務器支持此功能,則必須使用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來下載它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM