How to download multiple files using httpclient ?

Shalva Gabriel 61 Reputation points
2021-10-23T19:55:54.453+00:00

I created a class

using System;  
using System.Collections.Generic;  
using System.IO;  
using System.Linq;  
using System.Net.Http;  
using System.Text;  
using System.Threading.Tasks;  
  
namespace Download_Http  
{  
    class Downloader  
    {  
        public delegate void DownloadProgressHandler(long? totalFileSize, long totalBytesDownloaded, double? progressPercentage);  
  
        public static class DownloadWithProgress  
        {  
            public static async Task ExecuteAsync(HttpClient httpClient, string downloadPath, string destinationPath, DownloadProgressHandler progress, Func<HttpRequestMessage> requestMessageBuilder = null)  
            {  
                requestMessageBuilder ??= GetDefaultRequestBuilder(downloadPath);  
                var download = new HttpClientDownloadWithProgress(httpClient, destinationPath, requestMessageBuilder);  
                download.ProgressChanged += progress;  
                await download.StartDownload();  
                download.ProgressChanged -= progress;  
            }  
  
            private static Func<HttpRequestMessage> GetDefaultRequestBuilder(string downloadPath)  
            {  
                return () => new HttpRequestMessage(HttpMethod.Get, downloadPath);  
            }  
        }  
  
        internal class HttpClientDownloadWithProgress  
        {  
            private readonly HttpClient _httpClient;  
            private readonly string _destinationFilePath;  
            private readonly Func<HttpRequestMessage> _requestMessageBuilder;  
            private int _bufferSize = 8192;  
  
            public event DownloadProgressHandler ProgressChanged;  
  
            public HttpClientDownloadWithProgress(HttpClient httpClient, string destinationFilePath, Func<HttpRequestMessage> requestMessageBuilder)  
            {  
                _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));  
                _destinationFilePath = destinationFilePath ?? throw new ArgumentNullException(nameof(destinationFilePath));  
                _requestMessageBuilder = requestMessageBuilder ?? throw new ArgumentNullException(nameof(requestMessageBuilder));  
            }  
  
            public async Task StartDownload()  
            {  
                var requestMessage = _requestMessageBuilder.Invoke();  
                var response = await _httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead);  
                await DownloadAsync(response);  
            }  
  
            private async Task DownloadAsync(HttpResponseMessage response)  
            {  
                response.EnsureSuccessStatusCode();  
  
                var totalBytes = response.Content.Headers.ContentLength;  
  
                using (var contentStream = await response.Content.ReadAsStreamAsync())  
                    await ProcessContentStream(totalBytes, contentStream);  
            }  
  
            private async Task ProcessContentStream(long? totalDownloadSize, Stream contentStream)  
            {  
                var totalBytesRead = 0L;  
                var readCount = 0L;  
                var buffer = ArrayPool<byte>.Shared.Rent(_bufferSize);  
                var isMoreToRead = true;  
  
                using (var fileStream = new FileStream(_destinationFilePath, FileMode.Create, FileAccess.Write, FileShare.None, _bufferSize, true))  
                {  
                    do  
                    {  
                        var bytesRead = await contentStream.ReadAsync(buffer, 0, buffer.Length);  
                        if (bytesRead == 0)  
                        {  
                            isMoreToRead = false;  
                            ReportProgress(totalDownloadSize, totalBytesRead);  
                            continue;  
                        }  
  
                        await fileStream.WriteAsync(buffer, 0, bytesRead);  
  
                        totalBytesRead += bytesRead;  
                        readCount += 1;  
  
                        if (readCount % 100 == 0)  
                            ReportProgress(totalDownloadSize, totalBytesRead);  
                    }  
                    while (isMoreToRead);  
                }  
  
                ArrayPool<byte>.Shared.Return(buffer);  
            }  
  
            private void ReportProgress(long? totalDownloadSize, long totalBytesRead)  
            {  
                double? progressPercentage = null;  
                if (totalDownloadSize.HasValue)  
                    progressPercentage = Math.Round((double)totalBytesRead / totalDownloadSize.Value * 100, 2);  
  
                ProgressChanged?.Invoke(totalDownloadSize, totalBytesRead, progressPercentage);  
            }  
        }  
    }  
}  

I got error on this line on the ??=

requestMessageBuilder ??= GetDefaultRequestBuilder(downloadPath);  

So I changed it to this but not sure if it's the right way :

if (requestMessageBuilder != null)  
                    GetDefaultRequestBuilder(downloadPath);  

Then in Form1 I have a button and a progressbar and I did

using System;  
using System.Collections.Generic;  
using System.ComponentModel;  
using System.Data;  
using System.Drawing;  
using System.Linq;  
using System.Net.Http;  
using System.Text;  
using System.Threading.Tasks;  
using System.Windows.Forms;  
  
namespace Download_Http  
{  
    public partial class Form1 : Form  
    {  
        private const double V = 0.0;  
        Downloader dl = new Downloader();  
  
        public Form1()  
        {  
            InitializeComponent();  
        }  
  
        private void Form1_Load(object sender, EventArgs e)  
        {  
  
        }  
  
        private async Task button1_Click(object sender, EventArgs e)  
        {  
            long g = 64;  
            HttpClient client = new HttpClient();  
              
            Downloader.DownloadProgressHandler dl = new Downloader.DownloadProgressHandler(64, 64, V);  
            await Downloader.DownloadWithProgress.ExecuteAsync(client, "https://speed.hetzner.de/100MB.bin", @"d:\satImages\", progressBar1, () =>  
            {  
                var requestMessage = new HttpRequestMessage(HttpMethod.Get, @"d:\satImages\");  
                requestMessage.Headers.Accept.TryParseAdd("application/octet-stream");  
                return requestMessage;  
            });  
        }  
    }  
}  

I'm not sure what to put in this line in form1 : 64, 64, V is wrong and give error/s

Downloader.DownloadProgressHandler dl = new Downloader.DownloadProgressHandler(64, 64, V);  

And not sure what to put in this line : Put there progressBar1 is wrong and give error/s

await Downloader.DownloadWithProgress.ExecuteAsync(client, "https://speed.hetzner.de/100MB.bin", @"d:\satImages\", progressBar1, () =>  
Windows Forms
Windows Forms
A set of .NET Framework managed libraries for developing graphical user interfaces.
1,827 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,234 questions
{count} votes