C# Download File with Progress Bar
The following is a snippet of code to download a file in a Windows Forms application using C# and the System.Net.WebClient object. This code also updates a progress bar as the file is downloaded.
First, create a new windows forms application with C# as the target language. (NOTE: This works in any .NET framework version). Add a ProgressBar to the form and a BackgroundWorker control. Also add a Button to the form. The form will look something like this:

We need some kind of background thread to update the progress bar while the file is downloaded. If we tried to update the progress bar from the main thread, out app will just hang, allowing no user input, and the progress bar would not change until the file was completely downloaded. Instead, we need to let the main thread run separately from our lengthy download operation. Set the BackgroundWorker's properties like this:

Go to the Events view of the BackgroundWorker and double click each of its events so they are auto-wired up as shown here:

Double click the button to auto-wire up the event click event and call our background worker to start running asynchronously when the button is clicked. Your code will look something like this:
private void btnTestDownload_Click(object sender, EventArgs e)
{backgroundWorker1.RunWorkerAsync();
}
In the BackgroundWorker's DoWork method, we put the code to run the download on a separate thread. The code will look something like this:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{ // the URL to download the file fromstring sUrlToReadFileFrom = "http://devtoolshed.googlepages.com/filezilla_download.exe";
// the path to write the file tostring sFilePathToWriteFileTo = "C:\\filezilla_download.exe";
// first, we need to get the exact size (in bytes) of the file we are downloading Uri url = new Uri(sUrlToReadFileFrom);System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();
response.Close();
// gets the size of the file in bytesInt64 iSize = response.ContentLength;
// keeps track of the total bytes downloaded so we can update the progress barInt64 iRunningByteTotal = 0;
// use the webclient object to download the fileusing (System.Net.WebClient client = new System.Net.WebClient())
{ // open the file at the remote URL for readingusing (System.IO.Stream streamRemote = client.OpenRead(new Uri(sUrlToReadFileFrom)))
{ // using the FileStream object, we can write the downloaded bytes to the file systemusing (Stream streamLocal = new FileStream(sFilePathToWriteFileTo, FileMode.Create, FileAccess.Write, FileShare.None))
{ // loop the stream and get the file into the byte buffer int iByteSize = 0;byte[] byteBuffer = new byte[iSize];
while ((iByteSize = streamRemote.Read(byteBuffer, 0, byteBuffer.Length)) > 0) { // write the bytes to the file system at the file path specifiedstreamLocal.Write(byteBuffer, 0, iByteSize);
iRunningByteTotal += iByteSize;
// calculate the progress out of a base "100"double dIndex = (double)(iRunningByteTotal);
double dTotal = (double)byteBuffer.Length;
double dProgressPercentage = (dIndex / dTotal);int iProgressPercentage = (int)(dProgressPercentage * 100);
// update the progress barbackgroundWorker1.ReportProgress(iProgressPercentage);
}
// clean up the file streamstreamLocal.Close();
}
// close the connection to the remote serverstreamRemote.Close();
}
}
}
Now implement the BackgroundWorker's ProgressChanged event to update the progress bar. NOTE: You can ONLY update the progress bar in this method. This method synchronized back with the form's main thread. If you tried to update the progress bar from the DoWork method, you would get an exception because that is not on the same thread as the form. Here's the code:
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{progressBar1.Value = e.ProgressPercentage;
}
For convenience, in the result you can show a message that your file is downloaded to note that it is completely finished like this:
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{ MessageBox.Show("File download complete");}
Popular Articles
Last viewed:
- Connecting to SQL Server, Oracle, and MySQL with Database or Windows Authentication
- SQL Create Table Add Description to Column
- How to localize a BoundField / TemplateField HeaderText
- How to Highlight the Day in the ASP.NET Calendar Control with the SelectedDate Property
- ObjectDataSource TypeName with Constructor Parameters
- Building a Web Service in ASP.NET 3.5
Recent comments
- "Windows Client File Set" #Change this How?
21 hours 18 min ago - thanks
4 days 12 hours ago - VPN
1 week 2 days ago - string s = null;
s =
1 week 6 days ago - I am using following
2 weeks 1 day ago - Fantastic
2 weeks 5 days ago - Very Nice
2 weeks 6 days ago - Nice Document
2 weeks 6 days ago - tabela
3 weeks 4 days ago - Good work
4 weeks 1 day ago

go
go
progress bar & XmlReader
Could I use this or any similiar technique with XmlReader?
Strange problem concerning the progress bar update
I created a new project (VS 2008, .Net 3.5) like shown here. Everything is working fine except the MessageBox "File download complete" is shown when the progess bar is at approximately 30 %. This seems to be a timing issue because when I debug the process and have a breakpoint in "backgroundWorker1_ProgressChanged", the progress bar is updated fine. A "progressBar1.Update();" doesn´t make any difference. Any help is appreciated.
The only way this could happen
The only way this could be happening is if your download is failing early and exiting with a success case. This could be due to network traffic or some other issue. Make sure you did not accidently put a message box into your worker thread. Then make sure there are no early outs in your code that could cause it to finish at 30%.
Worked smoothly
Thanks for posting such a wonderful information. It was a perfect solution for my problem.
Thanks
Nice helpful, working post. Thanks.
Change the buffer type to long instead of int
90% sure that the issue with the arithmetic operation is because the file size is bigger than the Int32 size. Just change the buffer to a long (Int64) and try it again.
arithmetic operation resulted in an overflow
This works fine with small file but trying to download a bigger file (75MBs) i get an "arithmetic operation resulted in an overflow" exception..
any idea how to solve this?
thanks
Hiiii
Please give sample source code
What an article
Marvellous.......................
Streaming a large file from the hard drive
This code above is interested in only downloading a file from the web. To read in a large file from your hard drive such as a very large XML file, probably the best way to do this is using the FileStream object. You can find out more about it here:
http://msdn.microsoft.com/en-us/library/system.io.filestream.aspx
This will allow you to stream the file in one character at a time. Inside your loop that reads the file, you can update your progress bar and update your TreeView control.
NOTE: Make sure you are doing all of this streaming on a separate thread such as a background worker process. That way, your UI will update. If you run this streaming on your main thread, you will not see the progress bar or any other UI update and it will appear to "hang" until your file is completely streamed in.
hi thx for the code it work
hi thx for the code it work ok
but how to catch download errors when the file does not exists or no internet connection avaiable?
Catching download errors
There are a couple of ways to do this. If you attempt to download a file that does not exist (invalid URL) or that may have a connection drop/timeout, then there can be an exception thrown here.
If you want the code to prompt the user and let them retry, then put a try/catch block around the code in the background worker DoWork method. When the exception is thrown, allow them to restart the download with a dialog or other message box.
If you want to abort the operation, then you don't have to do anything because the background worker already handles exception packaging across threads for you. Just let the exception get thrown. Then in the background worker RunWorkerCompleted() method, you can get the result by checking the "e" RunWorkerCompletedEventArgs parameter. Check if the Error property is = null or not. If it is not null, then there will be the exception which you can display to the user there.
To download file from hard drive using progress bar & Background
Hi,
I have created a project to load xml file in Treeview in winform.
Now i want to add a progress bar which will show the time taken to get file from my memory to treeview.i want to use a background worker also.
I have treeview,Browse button(to select a file), textbox(to display the file name selected)
toolStripStatusLabel,toolStripStatusProgressBar.
Can you please help out..
This is very helpful article
Mine progressbar moves upto 6 count and then nothing else works. I have tried timer method, and other progress bar invalidate method. But from al these i have similar method. I cannot put background thread. Its very complex code and i cant change in between. Is there any other possible solution to update progressbar using the same main thread?
Update ProgressBar from main thread
Updating controls from your same thread during blocking operations like downloading a file will never work as well as a separate thread. You should really get into the habit of doing the updating from separate threads because this is core to doing advanced windows programming.
All of that being said, I did find a thread where you can create a delegate back to your thread that may work for you. Here is the post:
http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/093dfdb2-e...