question

ShalvaGabriel-1621 avatar image
0 Votes"
ShalvaGabriel-1621 asked JackJJun-MSFT commented

How to download multiple files using httpclient ?

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, () =>




dotnet-csharpwindows-forms
· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

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

For your question, we could not pass the value to the delegate directly. Also, I noticed that you only define the delegate and the event and you don't create the correspond method.

You could look at the microsoft doc how-to-declare-instantiate-and-use-a-delegate to design the method based on your requirement.

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

The code here we need to use the instance of DownloadProgressHandler-> dl.








0 Votes 0 ·

0 Answers