Click here to Skip to main content
Click here to Skip to main content

Windows Communication, Web Client Asynchronous File Downloader

By , 27 May 2008
 

Introduction

This project is intended to show how simple it is to implement an asynchronous downloader of an unlimited number of files, using the WebClient class. The key features are implemented using DownloadFileAsync and few callback functions which report progress information about active download.

The project does not use any additional threads. Everything is implemented using asynchronous callback methods which are called by the WebClient object when the internal state of the downloader changes.

Some Screen Shots

First of all, look at the program window when some parallel downloads are in progress. It’s possible to add as many download tasks as you want.

figure1.jpg
Figure 1. Multiple asynchronous download in progress.


figure2.jpg
Figure 2. Multiple asynchronous downloads finished. One has been cancelled and the second is completed.

Functional Concepts

figure3.jpg
Figure 3. Interaction diagram.

Initially, a main process is created which brings up to the user the main window with a input field for URI, an add button which starts the download process, and listview which is used to display status (in real time) of each WebClient (Figure 3). After the user presses the Add button ([+]), the DownloaderTask object creates a new downloader and assigns to it Progress Callback and End Callback events.

The download is started in the same turn. The resource is saved to the current folder and the name is automatically extracted from the last segment of the URI:

  fileName = this.uriData.Segments[this.uriData.Segments.Length - 1];

Logical Structure

figure4.jpg
Figure 4. Class diagram.

When the user presses the add button, a DownloaderTask object is created and added to the dwnTasks list (Figure 4):

dwnTasks.Add(new DownloaderTask(tbUri.Text, lvDownloads)); 

The first parameter represents the URI and the second is a listview, where the download task object itself creates an informational group for the downloaded file and continuously updates it. The DownloaderTask constructor will create a WebClient() object, then will assign callbacks:

    webClient.DownloadProgressChanged +=
        new DownloadProgressChangedEventHandler(webClient_DownloadProgressChanged);
webClient.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler
    (webClient_DownloadFileCompleted);

Also the constructor of the DownloaderTask object creates a group in passed listview (if not null) which will describe the current status of the downloadable file and the operation result at the end (See figure 2).

Conclusion

There are, of course, some TO DO items like:

  • Remove incomplete downloaded files (after failure or cancellation)
  • Allow a user to select destination folder and file name, etc.

History

  • 27th May, 2008: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Macari Veaceslav
Software Developer (Senior)
Moldova (Republic Of) Moldova (Republic Of)
He has Master degree in computer science. Started with microcontrollers programming from 2002 and do windows and linux programming till now.
 

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralType casting in "GetHumanReadableFileSize" causing small problem (not rounding to specified precision)memberamattice2-Nov-10 19:13 
In the method "GetHumanReadableFileSize", casting of types (and placement of parenthesese) is causing rounding to occur with integers instead of the precision specified in the logic.
 
Here's what the project is doing...
 
return String.Format("{0} Kb", (double)Math.Round((double)(fileSize /1024), 2));
 

Since filesize is an integer, the cast to double is occuring after the division by 1024, so the request to round to two decimal places doesn't do anything because the result of integer filesize divided by 1024 will be an integer result and therefore no decimal places exist.
 
This can be fixed by shuffling those parentheses, so the cast to double is performed on filesize and not on the result of filesize/1024.
 
return String.Format("{0} Kb", Math.Round((double)fileSize / 1024, 2));
 

The same concept applies well to the other two (all three) formatters in GetHumanReadableFileSize for Gb and Mb calculations.
Andy

GeneralScrolling issuememberandrewtheart17-Aug-08 11:41 
Ooh, I really wished that could be fixed. It's prefect otherwise
GeneralI think I'll use this in my projectmemberandrewtheart17-Aug-08 11:26 
I think I'm going to use this code in my own project. I'll give you credit where credit is due though. This is exactly what I was looking for!
 
The main issue I have is the fact that scrolling down the list of downloads is essentially useless as after a refresh of the data, the ListView scrolls back up to the top. Also, the flickering is bad but necessary I guess.
 
Good job!

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130617.1 | Last Updated 27 May 2008
Article Copyright 2008 by Macari Veaceslav
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid