I'm writing a library with intentions to use it in desktop (.Net 4.0 and up), phone (WP 7.5 and up) and Windows Store (Windows 8 and up) apps.
The library has the capability to download files from the Internet using Portable HttpClient library, and report the progress of the download.
I search around here and the rest of the internet for documentations and code sample/guidelines on how to implement the progress reporting, and this search led me to nowhere.
Does anyone has an article, documentation, guideline, code sample or whatever to help me achieve this?
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("\r%{0:N0}", value);
var cancellationToken = new CancellationTokenSource();
await DownloadFileAsync("http://www.dotpdn.com/files/Paint.NET.3.5.11.Install.zip", progress, cancellationToken.Token);
You can specify HttpCompletionOption.ResponseHeadersRead and then get the stream and report progress while you read from the stream. See this similar question.