6

http経由でファイルをダウンロードするプログラムを作っています。

ダウンロードしましたが、ダウンロードを一時停止し、プログラムを閉じて、後日再開できるようにしたいと思います。

私はそれらをダウンロードしている場所がこれをサポートしていることを知っています。

HttpWebResponseを介してファイルをダウンロードし、GetResponseStreamを使用して応答をストリームに読み込みます。

アプリを閉じて再起動すると、ダウンロードを再開する方法がわかりません。ストリームでシークを実行しようとしましたが、サポートされていないと表示されます。

これを行うための最良の方法は何でしょうか?

4

3 に答える 3

9

サーバーがこれをサポートしている場合は、 AddRangeメソッドを使用して、リクエストとともにRangeHttpヘッダーを送信する必要があります。

request.AddRange(1024);

これにより、1キロバイト後にファイルの送信を開始するようにサーバーに指示されます。次に、通常どおり応答ストリームを読み取ります。

サーバーが再開をサポートしているかどうかをテストするには、HEADリクエストを送信して、Accept-Ranges: bytesヘッダーを送信するかどうかをテストします。

于 2009-09-17T20:00:54.483 に答える
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();
        }

    }
}
于 2009-09-18T01:35:15.770 に答える
0

ソリューションは問題ありませんが、サーバーがContent-Lengthヘッダーを送信する場合にのみ機能します。このヘッダーは、動的に生成されたコンテンツには存在しません。

また、このソリューションは、読み取りごとにリクエストを送信します。リクエスト間でサーバー上のコンテンツが変更されると、一貫性のない結果が得られます。

データをローカルに(ディスクまたはメモリに)保存することで、これを改善します。その後、あなたはそれにあなたが望むすべてを探すことができます。不整合の問題はなく、ダウンロードするのに必要なHttpWebRequestは1つだけです。

于 2009-09-19T03:15:00.767 に答える