A Simple File Downloading Method with Progress Bar Updating
Many people have wondered how to download a file from the Internet while having a progress bar to track the download progress. In this example, I will demonstrate how to achieve this task. The article also covers how to get file complete percentage, bytes received, bytes left, and download speed (kb/sec).
The pictures below are snapshots off the downloadable example in this article. The code is fully commented for easy understanding and I will cover every aspect of the program in this article in detail so that coders can understand and implement this code on any program they want.

Note: The methods I used are probably not the fastest and most efficient out there, but that is the way I code. I hope that when you finish reading this article, you will be able to write such a thing yourself...so let's get started!
General Description
The program uses a worker thread to perform the file download; this is so that our main application won't be blocked and so that we could have a cancel download functionality inside the program. All the downloading is being done from inside the thread along with the on-screen updating; we will get into that in a minute.
Coding Time!
Note: The following code is just a general overview of how to perform these tasks. Look inside the program source code to see the actual implementation of the code below:
CInternetSession netSession;
CStdioFile *file;
file = netSession.OpenURL(char url,1,INTERNET_FLAG_TRANSFER_BINARY
| INTERNET_FLAG_RELOAD);
This function returns a pointer to a CStdioFile, which is currently the file we requested online. You now can process the file as it was on your local hard drive. I haven't tested writing into a file using this method but it probably will require the permission and access for the file write method on the specified server.
Reading from the File and Writing It to the Local Hard Drive
Reading from the file is quite easy; all we have to do is this:
file->Read(char buffer,int bytes to read);
CFile fl;
fl.Open("myfile",CFile::modeCreate | CFile::modeWrite
| CFile::typeBinary);
fl.Write(buffer,bytes read);
Progress Bar, Transfer Data, and More
To make our progress bar effective, we use the CProgressCtrl::SetRange32(); function. The parameters passed to the function are lower value and upper value; lower value is of course 0 and the upper value is the file size, which we determine by simply calling:
int x = file->SeekToEnd();
The ::SeekToEnd(); function returns the total bytes of the file, which is determined into a file size.
The updating of the progress bar is being made every time we read a chunk of the file. Our program uses chunks of 512 bytes, not to overload the connection. The progress is updated every time the program performs another file->Read(); function.
while(int bytesread = file->Read(charbuf,512))
{
currentbytes = currentbytes + bytesread;
CProgressCtrl::SetPos(currentbytes);
}
To calculate our bytes received, percentages, and download speed(kb/sec), use the following code.
int percent = currentbytes * 100 / x ( our file size integer
from above);
int kbreceived = currentbytes / 1024;
Calculating the download speed is a bit trickier. Before we go into the while loop, we create a COleDateTime object to get the current time and declare a variable (double) to store our seconds between the current time and the download start time.
COleDateTime dlStart = COleDateTime::GetCurrentTime(); double secs;
This function will get the time the download started. In the while loop, we declare a COleDateTimeSpan object to calculate the seconds between the download start and the current time.
COleDateTimeSpan dlElapsed = COleDateTime::GetCurrentTime()
- dlStart;
secs = dlElapsed.GetTotalSeconds();
Now "secs" holds the seconds between when we started downloading the file and now... dividing the seconds with the kbs received will result in the speed rate (kb/sec).
double kbsec = kbreceived / secs;
This is it, a general information on how to achive these tasks. The program also implements error handling by using the try and catch phrases to determine error messages and printing them out to the screen. Please refer to the source code for more information.
I hope this article helped you figure out everything you need to know about downloading a file from the Internet.

Comments
60MB Error
Posted by Paul Z on 03/21/2013 09:22pmThis application stops downloading at 60MB if the source file is quite big (say bigger 100MB). I set my buffer size to 2^19 = 524288 (bytes). I tried to debug and found byteswrite gets to be 0 when it stops while statement. Any approach to solve this? Thanks.
ReplyStops downloading at 60MB
Posted by Paul Z. on 03/21/2013 09:21pmThis application stops downloading at 60MB if the source file is quite big (say bigger 100MB). I set my buffer size to 2^19 = 524288 (bytes). I tried to debug and found byteswrite gets to be 0 when it stops while statement. Any approach to solve this? Thanks.
ReplyStops downloading at 60MB
Posted by Paul Z. on 03/21/2013 09:19pmHi All, I tried to use this application to download files larger than 100MB, but it stops downloading at 60MB. Timeout didn't happen. While statement quits just because byteswrite becomes 0 at that point. Any approach to solve this? Thanks.
ReplyMemory Leak !!!
Posted by chgyver on 05/11/2004 04:28amIf I click "CANCEL" Button as downloading... This prog. create memory leak msg... And you can solve this problem... Modify, AfxEndThread(0) ==> return 0; In DownloadFile(LPVOID pParam) ------------------------------------ if(nTerminate == 1) // See if we got a Cancel requesst { netSession.Close(); fDestFile.Close(); // Close our destination file fTargFile->Close(); // Close remote file delete fTargFile; // Delete the CStdioFile object to prevent leaks fTargFile = NULL; pwnd->SetDlgItemText(IDC_STATUS,"Download cancelled by user"); // Set satus bar text // AfxEndThread(0); // End thread ==> MODIFY !!! return 0; // new code !!! }ReplyNeed a time out
Posted by Herve3D on 04/13/2004 05:52amSometimes during a file downloading, the program stay endlessly in this line : while(int bytesread = file->Read(charbuf,512)) I think we need to add a time out. Someone know a smart solution for this problem?
Replymemory exception
Posted by Legacy on 02/09/2004 12:00amOriginally posted by: Peter R.
"delete fTargFile;" is executed twice in ProgressExDlg.cpp, so you need to remove the second one.
delete fTargFile;
Replyif(nDownloaded == 1)
{
pwnd->SetDlgItemText(IDC_STATUS,"Download complete");
delete fTargFile;
}
Memory Exception
Posted by Legacy on 10/20/2003 12:00amOriginally posted by: Kapil Suri
whenever i try to run it
Replyit gives memory exceptiion error
waiting for any one rpz
kapil231@rediffmail.com
SeekToEnd didn't work
Posted by Legacy on 10/04/2003 12:00amOriginally posted by: Yae Chan
When i was using SeekToEnd fuction it doesn't work as i expected. Any, thank you.
ReplyException Error (The Memory Could not be Read)
Posted by Legacy on 09/27/2003 12:00amOriginally posted by: Sachin Mundhra
When i run the application it gives Unhandled Exception.
Sachin
Replyneed help in resuming
Posted by Legacy on 02/03/2003 12:00amOriginally posted by: jag
can anybody help me in how to resume a download.
thank u
Replyjag
Loading, Please Wait ...