HttpClientを使ってファイルをダウンロードする時に進捗を表示することを実現します.
7695 ワード
frame efforkでファイルをダウンロードして進捗を表示するには、WebClientクラスを使うのが一番簡単です.DownloadProgress Changedイベントを購読すればいいです.
残念ながら、WebCientは.net standardに含まれていません.net standardの中でhttpネットの要求を行って、私達が使うのはもっと多いのがHttpClientです.また、UWPの中にもHttpClientがあります.使い方は似ていますが、名前空間は違っています.またUWPのはダウンロードの進捗をサポートしています.ここでは詳しく説明しません.
ファイルをダウンロードするなら、私たちはHttpClientのGetByteArayAryncという方法を使います.ダウンロードの進捗を実現するには、どうすればいいですか?よく言われていますが、だめなら一重に包んでください.ここでは拡張方法を書いて、次のように定義します.
http応答ヘッダからcontent-lengthを取得する必要があるので、HttpClient自身のGetByteArayAryncは実現できません.GetAryncを使用する方法に転向したいです.Get Aryncこの方法には重荷重があります.https://docs.microsoft.com/zh-cn/dotnet/api/system.net.http.httpclient.getasync#System_Net_Http_Http Client_Get Aync_System_同前System_Net_Http_HttpCompleetion Option_System_Threading_CancellationToken_第二のパラメータは列挙されていますが、いつごろからレスリングが得られますか?需要に応じて、私達はここでHttpCopletion Option.ReponseHeaders Readを使うべきです.
またHttpClientのソースコードもGithubで見られます.https://github.com/dotnet/corefx/blob/d69d441dfb0710c2a34155c7c4745db357b14c96/src/System.Net.Http/src/System/Net/Http/HttpClient.cs GetByteArayAryncの実現を参照することができます.
考えた結果、次のコードが書けます.
自分のデモの効果図を以下に示します.
残念ながら、WebCientは.net standardに含まれていません.net standardの中でhttpネットの要求を行って、私達が使うのはもっと多いのがHttpClientです.また、UWPの中にもHttpClientがあります.使い方は似ていますが、名前空間は違っています.またUWPのはダウンロードの進捗をサポートしています.ここでは詳しく説明しません.
ファイルをダウンロードするなら、私たちはHttpClientのGetByteArayAryncという方法を使います.ダウンロードの進捗を実現するには、どうすればいいですか?よく言われていますが、だめなら一重に包んでください.ここでは拡張方法を書いて、次のように定義します.
public static class HttpClientExtensions
{
public static Task<byte[]> GetByteArrayAsync(this HttpClient client, Uri requestUri, IProgress progress, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
}
その中のHttpDownloadPrograssは自分で定義した構造体です.コードは以下の通りです.public struct HttpDownloadProgress
{
public ulong BytesReceived { get; set; }
public ulong? TotalBytesToReceive { get; set; }
}
Bytes Receivedはダウンロード済みのバイト数を表し、TotalBytes ToReceiveはダウンロードが必要なバイト数を表しています.httpの応答ヘッダは必ずしも長さに戻るとは限らないので、ここでは空きがあります.http応答ヘッダからcontent-lengthを取得する必要があるので、HttpClient自身のGetByteArayAryncは実現できません.GetAryncを使用する方法に転向したいです.Get Aryncこの方法には重荷重があります.https://docs.microsoft.com/zh-cn/dotnet/api/system.net.http.httpclient.getasync#System_Net_Http_Http Client_Get Aync_System_同前System_Net_Http_HttpCompleetion Option_System_Threading_CancellationToken_第二のパラメータは列挙されていますが、いつごろからレスリングが得られますか?需要に応じて、私達はここでHttpCopletion Option.ReponseHeaders Readを使うべきです.
またHttpClientのソースコードもGithubで見られます.https://github.com/dotnet/corefx/blob/d69d441dfb0710c2a34155c7c4745db357b14c96/src/System.Net.Http/src/System/Net/Http/HttpClient.cs GetByteArayAryncの実現を参照することができます.
考えた結果、次のコードが書けます.
public static class HttpClientExtensions
{
private const int BufferSize = 8192;
public static async Task<byte[]> GetByteArrayAsync(this HttpClient client, Uri requestUri, IProgress progress, CancellationToken cancellationToken)
{
if (client == null)
{
throw new ArgumentNullException(nameof(client));
}
using (var responseMessage = await client.GetAsync(requestUri, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false))
{
responseMessage.EnsureSuccessStatusCode();
var content = responseMessage.Content;
if (content == null)
{
return Array.Empty<byte>();
}
var headers = content.Headers;
var contentLength = headers.ContentLength;
using (var responseStream = await content.ReadAsStreamAsync().ConfigureAwait(false))
{
var buffer = new byte[BufferSize];
int bytesRead;
var bytes = new List<byte>();
var downloadProgress = new HttpDownloadProgress();
if (contentLength.HasValue)
{
downloadProgress.TotalBytesToReceive = (ulong)contentLength.Value;
}
progress?.Report(downloadProgress);
while ((bytesRead = await responseStream.ReadAsync(buffer, 0, BufferSize, cancellationToken).ConfigureAwait(false)) > 0)
{
bytes.AddRange(buffer.Take(bytesRead));
downloadProgress.BytesReceived += (ulong)bytesRead;
progress?.Report(downloadProgress);
}
return bytes.ToArray();
}
}
}
}
ここではバッファエリアを8192バイト(8 KB)に設定します.読み取り8 KBごとにダウンロードの進捗度を報告します.もちろん、視聴者の皆様もこの値を小さくしてもいいです.効果はもっといいですが、相対的な性能はちょっと悪いです.また、ここではReportの周波数が高いため、HttpDownloadPrograssはclassを使うのに適していません.自分のデモの効果図を以下に示します.