3

I have a small app that downloads some files from a remote (HTTP) server to the users local hard drive, some of the files are large, but I don't know just how large at run time. Is there any method that will allow me download a file with some type of progress meter?

This is a WinForms app, right now I'm using WebClient.DownloadFile() to download the file.

Edit: I've looked into the DownloadProgressChanged and OnDownloadProgressChanged events and they seem to work fine, but they will not work for my solution. I am downloading several files and if I use WebClient.DownloadFileAsync then the event is called several times/second because each file calls it.
Here is the basic structure of the app:

  • Download a list of files typically about 114
  • Run a loop over the list of files and download each one to its desination

I don't mind downloading each file seperatly but without downloading them with DownloadFileAsync() I cannot use the event handlers.

UnkwnTech
  • 88,102
  • 65
  • 184
  • 229

4 Answers4

5

Use WebClient.OnDownloadProgressChanged. Keep in mind, it's only possible to calculate progress if the server reports the size up front.

EDIT:

Looking at your update, what you can try is making a queue of URLs. Then, when a file finishes downloading (DownloadDataCompleted event), you will launch the async download of the next URL in the queue. I haven't tested this.

Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
  • OnDownloadProgressChanged is a method and will not help the OP. All it does is raise the DownloadProgressChanged event as in my answer. Catching the event is what's required. – stevehipwell Jul 10 '09 at 08:14
  • 2
    I think you're nit-picking, Stevo. Yes, catching the event is required, and I never said otherwise. – Matthew Flaschen Jul 10 '09 at 08:22
  • You would never use OnDownloadProgressChanged, all the Op needs to do is catch an event. OnDownloadProgressChanged just confuses the matter. – stevehipwell Jul 10 '09 at 08:28
2

Handle the WebClient DownloadProgressChanged event.

stevehipwell
  • 56,138
  • 6
  • 44
  • 61
1

I've just written this and it definately appears to do what you want.

Also, within the ProgressChanged Event you've got the "TotalBytesToReceive" property and the "BytesReceived" property.

private void StartDownload()
{

    // Create a new WebClient instance.
    WebClient myWebClient = new WebClient();

    // Set the progress bar max to 100 for 100%
    progressBar1.Value = 0;
    progressBar1.Maximum = 100;

    // Assign the events to capture the progress percentage
    myWebClient.DownloadDataCompleted+=new DownloadDataCompletedEventHandler(myWebClient_DownloadDataCompleted);
    myWebClient.DownloadProgressChanged+=new DownloadProgressChangedEventHandler(myWebClient_DownloadProgressChanged);

    // Set the Uri to the file you wish to download and fire it off Async
    Uri uri = new Uri("http://external.ivirtualdocket.com/update.cab");
    myWebClient.DownloadFileAsync(uri, "C:\\Update.cab");

}

void myWebClient_DownloadProgressChanged(object sender, System.Net.DownloadProgressChangedEventArgs e)
{
    progressBar1.Value = e.ProgressPercentage;
}

void myWebClient_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
    progressBar1.Value = progressBar1.Maximum;
}
djdd87
  • 67,346
  • 27
  • 156
  • 195
1

I needed to solve a similar problem, and GenericTypeTea's code example did the trick; except that I discovered that the DownloadDataCompleted event is not fired when you call the DownloadFileAsync method. Instead, the DownloadFileCompleted event is raised.

dan9298
  • 195
  • 1
  • 11