C#でファイルダウンロードの進捗状況を表示する

2020.12.16

はじめに

C#で進捗が分かるファイルダウンロードの方法を調べました。ダウンロードの方法はいくつか試したのですが進捗状況が意外と取れなくて、他に進捗状況を出す方法が見つけられませんでした。UWPで作ったテストアプリのソースコードは以下になります。実際はProgressBarで進捗状況を表示すると思いますが、今回はコンソールに表示しています。画面側はボタン1つ置いただけの画面なので割愛します。このサンプルではビデオライブラリにダウンロードしたファイルを置いていますので、Package.appxmanifestの機能の設定で「ビデオ ライブラリ」を許可する必要があります。

UWPのソースコード

using System;
using System.Diagnostics;
using Windows.Storage;
using Windows.Storage.Streams;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.Web.Http;

namespace SampleDownload
{
    public sealed partial class MainPage : Page
    {
        private const string URI = "URI";
        private const string FILE_NAME = "ファイル名";

        public MainPage()
        {
            this.InitializeComponent();
        }

        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            StorageFolder storageFolder = KnownFolders.VideosLibrary;
            StorageFile file = await storageFolder.CreateFileAsync(FILE_NAME,
                CreationCollisionOption.ReplaceExisting);

            using (var fileStream = await file.OpenAsync(FileAccessMode.ReadWrite))
            {
                var client = new HttpClient();
                var response = await client.GetAsync(new Uri(URI), HttpCompletionOption.ResponseHeadersRead);
                double contentTotal = (double)response.Content.Headers.ContentLength;

                using (var inputStream = await response.Content.ReadAsInputStreamAsync())
                {
                    double readTotal = 0;
                    while (true)
                    {
                        IBuffer buffer = new Windows.Storage.Streams.Buffer(1024);
                        buffer = await inputStream.ReadAsync(buffer, buffer.Capacity, InputStreamOptions.None);

                        if (buffer.Length == 0)
                        {
                            break;
                        }

                        readTotal += buffer.Length;
                        double percent = readTotal * 100 / contentTotal;
                        Debug.WriteLine("Progress: {0}% ", Math.Round(percent, 1, MidpointRounding.AwayFromZero));
                        await fileStream.WriteAsync(buffer);
                    }
                }
            }
        }
    }
}