Click here to Skip to main content
15,867,568 members
Articles / Programming Languages / C#

Downloader Class

Rate me:
Please Sign up or sign in to vote.
3.26/5 (9 votes)
22 Dec 2009CPOL5 min read 29.6K   1.4K   26   10
A simple class that can download files to your PC.

Introduction 

From comments below:  

I made the class so it is easy to make a multi-downloading download client, and I like many small classes rather than a few huge ones, so I added this. One would hope that it isn't too hard to understand the coding with my unusual coding semantics. It is really here as a starting point for people looking to build a Download manager them selves. I tried to keep the coding simple so it is reasonably easy to understand. It is too easy for a beginner to see a huge class and not read it, just execute some of it's methods, I didn't want that to happen with this. I hoped it would be something that some one can read and learn some of the concepts of file downloads. It may not be a useful class on it's own but it should be educational. 

 

A simple class that can be added to your program to add download functionality. It is very useful to me in my Podcatcher program.  It uses Streams to download the files.  The main variables that make this work are

 	private Stream strResponse; 

        private Stream strLocal;

        private HttpWebRequest webRequest;

        private HttpWebResponse webResponse; 

The strResponse is used to stream the data from the server into the application, this is then picked up by the strLocal which is used to save the data to the disk.   The webRequest and webResponse are used to negotiate the download with the server.

The main download method works by first asking the server to start sending the file by creating the webRequest with the URL of the file like so:

C#
  	webRequest = (HttpWebRequest)WebRequest.Create(fileURL);

There is then some credential negotiation which is set to the default, if you have credentials to the file then you would have to create them.  Finally the server's response is saved in memory as webResponse.  The fileSize var is then set to this value so the program knows how many bytes it is downloading.  The fileSize var has to be a 64 bit integer so it can store the large numbers assoc. with the number of bytes in a file.  If you KNOW you are going to be downloading files where the fileSize in bytes can be stored in a smaller var then it is OK to change it, but I do not recommend it. 

Once the code has negotiated with the server a WebClient is then used to set the strRepsonse to the file on the server.  The code then creates a stream to the local disk, it uses the filePATH which is now set to the file's path and contains the name and extension too due to the parsing that happens on creation.  Once that is done the buffers and byte sizes are set and the code begins to read each byte from the server and write it to the disk. 

Easy! 

Once that has done the code closes the two streams and claims it has done using a bool locally stored.  You could use event handlers here to throw a new even if you wanted for download completion. 

Using the Code 

I tried to make this code perform well in MTAs (multi-threaded applications) so the start download function opens a new thread. If you don't want it to do this for example, it is created in a thread. And if you don't want nesting of threads, then it is easy to remove that.

C#
Download dl = new Download("url", "path", "name");

I have built the class assuming that you are wanting to start the download immediately, so the creation method will run the start() method to get the download going, but you could edit the class to start it when you want, by calling:

C#
dl.start();

The instantiation also does some path stuff, getting the extension from the URL automatically, so don't add that to the name - it will look silly. E.g.: for, aDoc.txt.txt just use the URL of the file, the location it must be saved to, and the name without the extension.

There is also a stop function which may be helpful, it is cunningly called stop().

C#
dl.stop();

Because this class is threaded already, you can get the current progress without pausing the operation to update the UI; I found this quite helpful. The progress is outputted as a percent by a public integer. There is also a string for the status that will display the current progress in the format "Downloaded " + BytesRead + " out of " + TotalBytes + " (" + PercentProgress + "%)", but that would be easy to change.

C#
public string status;

public int progress;

Points of Interest

A very easy way of managing many downloads is to use a collection, I found this to be the easiest way of using the code. While I am sure an array would do the same, the collection has a little more functionality, and it is easy to add and remove downloads as needed.

I have had a few issues with some of the stop method calling. If you get that too, just replace the code in stop() with thrDownload.Abort();. You could make the thrDownload public too for some added control, although I doubt it is necessary to most users. 

Something I also noticed while playing with the code is that it automatically resumes if a download is stopped - so you don't need to worry about crashes or pausing, just run stop() to hold the download and running start() with the same file name and url in place (use the same instantiated class for example) to resume the download.  

Why use this code 

I have made this code to be as efficient in threading as I can, it is very easy to start up a download with this and leave it going in the background.  I also made it so it is easy to build a download manager (DLM).  A simple List like

C#
List<Download> dlList = new List<Download>(); 

is a great way to manage many downloads, it already contains the name, url, destination and completed percentage so is offering it's self to a DLM using some sort of UI.  It would not be hard for the class to store things like descriptions or start times either, by making the constructor method look like this:  

C#
public string _Description;
public DateTime startedAt;
public Download(string url, string path, string name, string description)
{
    //Ininitialization
    //Start a download
    filePATH = path + "\\" + getFilename(url, name);
    fileURL = url;
    _Description = description;
    startedAt = DateTime.Now;
    start();
} 

Most importantly it gives you a uniform starting point from where to start building any sort of download manager, or just to add some features from an existing app

Autoresume is a very nice feature too 

History   

  • 12/12/2009 - Uploaded the article.  
  • 12/12/2009 - Added some more information about how the code works  
  • 12/12/2009 - Added "Why use this code" section 
  • 22/12/2009 - Added information about auto-resuming after a stop. 

License

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


Written By
Software Developer (Junior) Graymalkin
United Kingdom United Kingdom
A nerdy student from south devon.

Comments and Discussions

 
GeneralThe Coding Standard... Pin
Alexander Müller12-Dec-09 8:57
Alexander Müller12-Dec-09 8:57 
GeneralRe: The Coding Standard... Pin
Simon Cooksey12-Dec-09 9:22
Simon Cooksey12-Dec-09 9:22 
GeneralRe: The Coding Standard... Pin
Sergey Morenko22-Dec-09 11:35
professionalSergey Morenko22-Dec-09 11:35 
AnswerRe: The Coding Standard... Pin
Johann Gerell13-Dec-09 23:04
Johann Gerell13-Dec-09 23:04 
GeneralNot enough information Pin
Richard MacCutchan12-Dec-09 6:24
mveRichard MacCutchan12-Dec-09 6:24 
GeneralRe: Not enough information Pin
Simon Cooksey12-Dec-09 6:26
Simon Cooksey12-Dec-09 6:26 
Sure, I shall edit it now. Thanks for the feed back.
GeneralRe: Not enough information Pin
Simon Cooksey12-Dec-09 6:35
Simon Cooksey12-Dec-09 6:35 
GeneralRe: Not enough information Pin
Richard MacCutchan12-Dec-09 7:01
mveRichard MacCutchan12-Dec-09 7:01 
GeneralRe: Not enough information Pin
Simon Cooksey12-Dec-09 7:09
Simon Cooksey12-Dec-09 7:09 
GeneralRe: Not enough information Pin
Richard MacCutchan13-Dec-09 0:01
mveRichard MacCutchan13-Dec-09 0:01 

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.