Click here to Skip to main content
15,886,788 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hello, Guys.

Could you please provide me with a good solution for downloading a file from URL to local disk showing progress bar?

I tried to use OpenURL and Read of CInternetSession, but it failed in 60MB if I try to download large files ( > 60 MB).

Thanks.
Posted
Comments
enhzflep 22-Mar-13 0:17am    
I just do the downloading from a separate thread, using sockets.
Each time a I get some bytes from the recv function, I call a callback (which was supplied to the threadDownload function in it's initial threadData). This callback notifies the main window of the current progress.

The same mechanism I use when using multi-threaded drawing operations to notify the owning window that drawing operations have concluded and that the image may be blitted to screen.
H.Brydon 22-Mar-13 0:39am    
If you made that a solution I would have +5'd it.
enhzflep 22-Mar-13 0:43am    
Cheers. I'll put together something more comprehensive and post that as an answer. :)
Mohibur Rashid 22-Mar-13 1:21am    
waiting for the answer

1 solution

As I mentioned in a comment, the way I do it is to call a callback function in the function that reads data from the connection. This callback sends notification to the main window that there is updated download progress available. The main window then displays this information.

Here's a short example of the mechanism in use:

1. Code to handle button click in program's main window
C++
void onTestBtn()
{
    downloadHeader_t curDownload;
    char fileName[MAX_PATH];
    int i, numFiles;

    numFiles = sizeof(szUrls) / sizeof(*szUrls);

    ListView_DeleteAllItems(listWnd);
    for (i=0; i<numFiles; i++)
        addListViewItem(listWnd, szUrls[i]);

    downloadList.clear();
    for (i=0; i<numFiles; i++)
    {
        curDownload.szUrl = szUrls[i];
        curDownload.callback = (voidFuncPtr)fileDownloadedCallbackFunc;
        curDownload.progCallback = (voidFuncPtr)fileProgressCallbackFunc;
        curDownload.saveFilePath = getFilename(curDownload.szUrl);
        curDownload.lParam = (void*)i;
        curDownload.contentLen = 0;
        curDownload.bCancelled = false;
        downloadList.push_back(curDownload);
    }

    for (i=0; i<numFiles; i++)
    {
        _beginthread(DownloadThread, NULL, (void*)&(downloadList[i]));
    }
}


2. The callback function itself
C++
void fileProgressCallbackFunc(PVOID data)
{
    SendMessage(mainDlgWnd, WM_FILE_DOWNLOAD_PROGRESS_AVAILABLE, 0, (LPARAM)data);
}



3. Calling the callback (buried in DownloadThread(*void) )
C++
if (hdr->progCallback)
    hdr->progCallback(hdr);


4. Handling the message posted in the callback function - in the windowProcedure of the main window
C++
case WM_FILE_DOWNLOAD_PROGRESS_AVAILABLE:
    progHdr = (downloadHeader_t*)lParam;

    if (progHdr->bComplete)
        sprintf(buffer, "Complete");
    else
    {
        if (progHdr->contentLen > 1024*1024)
            sprintf(buffer, "%.2f MB", (float)progHdr->contentLen / (1024*1024) );
        else if (progHdr->contentLen > 1024)
            sprintf(buffer, "%.1f KB", (float)progHdr->contentLen / (1024) );
        else
            sprintf(buffer, "%.1f B", (float)progHdr->contentLen);

    }

    setListViewItemDownloaded(listWnd, (int)progHdr->lParam, buffer);


5. The definition of downloadHeader_t
C++
typedef void (*voidFuncPtr)(void*);
struct downloadHeader_t
{
    string szUrl;             /* in */
    voidFuncPtr callback;     /* in */
    voidFuncPtr progCallback;   /* in */
    string saveFilePath;     /* in */
    PVOID lParam;             /* in */

    SOCKET conn;
    char *readBuffer, *sendBuffer, *tmpBuffer, *result;
    string server, filepath, filename;
    long thisReadSize, headerLen, contentLen, totalLen;
    string statusTxt;
    bool bCancelled;
    bool bComplete;
};
 
Share this answer
 

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



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900