tags:

views:

930

answers:

4

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.

+4  A: 

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
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.
Stevo3000
I think you're nit-picking, Stevo. Yes, catching the event is required, and I never said otherwise.
Matthew Flaschen
You would never use OnDownloadProgressChanged, all the Op needs to do is catch an event. OnDownloadProgressChanged just confuses the matter.
Stevo3000
+2  A: 

Handle the WebClient DownloadProgressChanged event.

Stevo3000
Reason for down-vote?
Stevo3000
+1  A: 

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;
}
GenericTypeTea
+1  A: 

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