HttpClient
doesn't support progress. Your code isn't actually doing what you think it is in my opinion. You're tracking the progress of reading the stream but to get that stream you've already used the client to send the request and get the response. Whether the stream you're reading has already read all the contents or not is an implementation detail partially tied to the client and server impl. For large files it may behave the way you want but for small downloads it likely has already gotten all the content.
Here's a library I've never used that supposedly adds progress reporting to HttpClient
. I would recommend you use it.
The second problem is how to report progress to progressBar1 or labels ? how to add events like progress changed completed ?
Use the library I mentioned. Their readme shows you how to handle progress notifications. However be aware that the code is async so you need to marshal the event back to the UI thread. Something like this might work.
progress.ProgressChanged += OnDownloadProgress;
void OnDownloadProgress ( object sender, float progress )
{
if (_progressBar1.InvokeRequired)
_progressBar1.Invoke(OnDownloadProgress, new object[] { progress });
else
_progressBar1.Value = (int)progress; //Assuming the progress is between 0 and 100
}
When the download call returns the download is complete so do any post-processing at that point.
how to download multiple files from a list<string> or url's ?
To download more than 1 file at a time you'll need to start the downloads and not wait for the results until all downloads are started. For example assume that you are getting the list of files to download then you'd do something like this.
async Task DownloadFilesAsync ( string[] files )
{
var tasks = new List<Task>();
foreach (var file in files)
{
tasks.Add(DownloadFileAsync(file));
};
await Task.WhenAll(tasks);
}
Task DownloadFIleAsync ( string file )
{
//Your download code for a single file goes here
}
Note that the above is just starter code. You'll need to flush it out with any data you might want to return. You would also need to adjust your progress bar for downloading multiple files. Also be aware that you really shouldn't be creating HttpClient
instances in your code haphazardly. They are shared resources and need to be cleaned up otherwise you'll run out of ports. The best option is to create a single HttpClient
instance for your app (or per base URL) and reuse it. HttpClient
is thread safe provided you don't modify the base address or default request headers. If you need to send per-request headers then use the SendAsync
method that accepts the HttpRequestMessage
that you can provide.
If you don't particularly care about HttpClient
then you might find WebClient to be easier to use and it supports progress notifications automatically.