web-dev-qa-db-ja.com

.NETで再開/再試行をサポートするHTTPから大きなファイルをダウンロードしますか?

アプリケーションにHTTPから大きなファイル(〜500MB)をダウンロードする方法を教えてください。自動再開/再試行をサポートしたいので、接続が切断されたときに、アプリケーションが再接続を試みてファイルを取得し、可能であればダウンロードした部分の再ダウンロードを回避できます(これはサーバーにも依存します)。

これは、ダウンロードマネージャーや一部のブラウザーでの動作に似ています。

21
Louis Rhys

次の2つの方法のいずれかを使用して、C#のWebサーバーからのダウンロードを最初から実装できます。

  1. HttpWebRequestHttpWebResponseFtpWebRequest、およびその他のクラスなどのSystem.Netの高レベルAPIの使用。

  2. TcpClientTcpListener、SocketクラスなどのSystem.Net.Socketsの低レベルAPIの使用。

最初のアプローチを使用する利点は、通常、HTTPヘッダーの準備と解釈、プロキシの処理、認証、キャッシュなどの低レベルの配管について心配する必要がないことです。高レベルのクラスがこれを行うため、私はこのアプローチを好みます。

最初の方法を使用すると、URLからファイルをダウンロードするためのHTTPリクエストを準備する一般的なコードは次のようになります。

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
if (UseProxy)
{
    request.Proxy = new WebProxy(ProxyServer + ":" + ProxyPort.ToString());
    if (ProxyUsername.Length > 0)
        request.Proxy.Credentials = new NetworkCredential(ProxyUsername, ProxyPassword);
}
//HttpWebRequest hrequest = (HttpWebRequest)request;
//hrequest.AddRange(BytesRead); ::TODO: Work on this
if (BytesRead > 0) request.AddRange(BytesRead);

WebResponse response = request.GetResponse();
//result.MimeType = res.ContentType;
//result.LastModified = response.LastModified;
if (!resuming)//(Size == 0)
{
    //resuming = false;
    Size = (int)response.ContentLength;
    SizeInKB = (int)Size / 1024;
}
acceptRanges = String.Compare(response.Headers["Accept-Ranges"], "bytes", true) == 0;

//create network stream
ns = response.GetResponseStream();        

上記のコードの最後で、ネットワークストリームオブジェクトを取得します。これを使用して、他のストリームオブジェクトを読み取る場合と同じように、リモートファイルのバイトを読み取ることができます。ここで、リモートURLが任意の位置からの読み取りを許可することで部分的なダウンロードの再開をサポートするかどうかは、 "Accept-Ranges"HTTPヘッダーによって示されます。上記。この値が「バイト」以外に設定されている場合、この機能はサポートされません。

実際、このコードは、私がC#で実装しようとしている、より大きなオープンソースのダウンロードマネージャーの一部です。あなたはこのアプリケーションを参照して、あなたに役立つものがあるかどうかを確認することができます: http://scavenger.codeplex.com/

12
Prahlad Yeri

自動再開/再試行サポート(サーバーがサポートしている場合)を備えたオープンソースの.Net httpファイルダウンローダーがあり、それがまさに必要なもののように見え、それを使用してみることができます。

https://github.com/Avira/.NetFileDownloader

6
leonid p