A Simple File Downloading Method with Progress Bar Updating

Environment: Compiled and tested on VC++ 5.0 and 6.0; running Windows 2000/NT/XP

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.

Downloads

Download project workspace - 47 Kb