How to implement progress reporting for Portable H

2019-01-14 10:00发布

问题:

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?

回答1:

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);


回答2:

You can specify HttpCompletionOption.ResponseHeadersRead and then get the stream and report progress while you read from the stream. See this similar question.