I wrote the following code to implement progress reporting. The code supports all the platforms I wanted; however, you need to reference the following NuGet packages:
- Microsoft.Net.Http
- Microsoft.Bcl.Async
Here is the code:
public async Task DownloadFileAsync(string url, IProgress<double> progress, CancellationToken token)
{
var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token);
if (!response.IsSuccessStatusCode)
{
throw new Exception(string.Format("The request returned with HTTP status code {0}", response.StatusCode));
}
var total = response.Content.Headers.ContentLength.HasValue ? response.Content.Headers.ContentLength.Value : -1L;
var canReportProgress = total != -1 && progress != null;
using (var stream = await response.Content.ReadAsStreamAsync())
{
var totalRead = 0L;
var buffer = new byte[4096];
var isMoreToRead = true;
do
{
token.ThrowIfCancellationRequested();
var read = await stream.ReadAsync(buffer, 0, buffer.Length, token);
if (read == 0)
{
isMoreToRead = false;
}
else
{
var data = new byte[read];
buffer.ToList().CopyTo(0, data, 0, read);
// TODO: put here the code to write the file to disk
totalRead += read;
if (canReportProgress)
{
progress.Report((totalRead * 1d) / (total * 1d) * 100);
}
}
} while (isMoreToRead);
}
}
The using it is as simple as:
var progress = new Microsoft.Progress<double>();
progress.ProgressChanged += (sender, value) => System.Console.Write("
%{0:N0}", value);
var cancellationToken = new CancellationTokenSource();
await DownloadFileAsync("http://www.dotpdn.com/files/Paint.NET.3.5.11.Install.zip", progress, cancellationToken.Token);
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…