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


Comments

  • 60MB Error

    Posted by Paul Z on 03/21/2013 09:22pm

    This 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.

    Reply
  • Stops downloading at 60MB

    Posted by Paul Z. on 03/21/2013 09:21pm

    This 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.

    Reply
  • Stops downloading at 60MB

    Posted by Paul Z. on 03/21/2013 09:19pm

    Hi 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.

    Reply
  • Memory Leak !!!

    Posted by chgyver on 05/11/2004 04:28am

    If 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 !!!
    		}

    Reply
  • Need a time out

    Posted by Herve3D on 04/13/2004 05:52am

    Sometimes 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?

    Reply
  • memory exception

    Posted by Legacy on 02/09/2004 12:00am

    Originally posted by: Peter R.

    "delete fTargFile;" is executed twice in ProgressExDlg.cpp, so you need to remove the second one.

    delete fTargFile;
    if(nDownloaded == 1)
    {
    pwnd->SetDlgItemText(IDC_STATUS,"Download complete");
    delete fTargFile;
    }

    Reply
  • Memory Exception

    Posted by Legacy on 10/20/2003 12:00am

    Originally posted by: Kapil Suri

    whenever i try to run it
    it gives memory exceptiion error
    waiting for any one rpz
    kapil231@rediffmail.com

    Reply
  • SeekToEnd didn't work

    Posted by Legacy on 10/04/2003 12:00am

    Originally posted by: Yae Chan

    When i was using SeekToEnd fuction it doesn't work as i expected. Any, thank you.

    Reply
  • Exception Error (The Memory Could not be Read)

    Posted by Legacy on 09/27/2003 12:00am

    Originally posted by: Sachin Mundhra

    When i run the application it gives Unhandled Exception.

    Sachin

    Reply
  • need help in resuming

    Posted by Legacy on 02/03/2003 12:00am

    Originally posted by: jag

    can anybody help me in how to resume a download.

    thank u
    jag

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Protecting business operations means shifting the priorities around availability from disaster recovery to business continuity. Enterprises are shifting their focus from recovery from a disaster to preventing the disaster in the first place. With this change in mindset, disaster recovery is no longer the first line of defense; the organizations with a smarter business continuity practice are less impacted when disasters strike. This SmartSelect will provide insight to help guide your enterprise toward better …

  • Live Event Date: August 20, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT When you look at natural user interfaces as a developer, it isn't just fun and games. There are some very serious, real-world usage models of how things can help make the world a better place – things like Intel® RealSense™ technology. Check out this upcoming eSeminar and join the panel of experts, both from inside and outside of Intel, as they discuss how natural user interfaces will likely be getting adopted in a wide variety …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds