Download demo project - 23 Kb
Downloading with URLDownloadToFile()
A while ago, Chris Maunder posted a suggestion to one of the boards asking how to download files, with the ability to abort the download after a timeout period. One solution to doing this is a function provided by IE 3 and later called URLDownloadToFile()
. This function is suprisingly simple - just give it a URL, a filename, and an object to handle progress callbacks, and IE handles the rest!
The function can be used by any application rather easily. IE displays no UI during the download, so the caller can provide any desired progress indicators. IE informs the caller of the download progress, so showing progress UI is also pretty easy.
The prototype for URLDownloadToFile()
is:
HRESULT URLDownloadToFile(
LPUNKNOWN pCaller,
LPCSTR szURL,
LPCSTR szFileName,
DWORD dwReserved,
LPBINDSTATUSCALLBACK lpfnCB);
pCaller
- is used only if the caller is an ActiveX object. If the calling app is not an ActiveX object, this parameter can be NULL.
szURL
- is the absolute URL of the file to download.
szFileName
- contains the fully-qualified name of the file to be created.
dwReserved
- must be zero.
lpfnCB
- is a pointer to an
IBindStatusCallback
interface, which IE uses to inform you of the download progress.
The steps involved in using URLDownloadToFile()
are:
- Obtain the URL for the file you want to download.
- Construct the fully-qualified path for the file to be created.
- Create an
IBindStatusCallback
-derived class and write an OnProgress()
function for it.
- Instantiate an object of that class.
- Call
URLDownloadToFile()
. The call is synchronous, so you will probably want to call the function from a worker thread.
- In your
OnProgress()
function, provide any progress indicators or other UI that you want. The return from OnProgress()
tells IE whether to continue the download, or abort it.
Using IBindStatusCallback
IBindStatusCallback
has eight methods, but for the purposes of downloading, the only function you need to be concerned with is OnProgress()
. The others can just return E_NOTIMPL
. The prototype for OnProgress()
is:
HRESULT OnProgress(
ULONG ulProgress,
ULONG ulProgressMax,
ULONG ulStatusCode,
LPCWSTR szStatusText );
ulProgress
- is the number of bytes downloaded so far.
ulProgressMax
- is the size of the file, or zero if the size is not known. Note that technically, this value may change between calls to
OnProgress()
, so you should not store the value in a static variable; you should check the value every time the function is called.
ulStatusCode
- is a number indicating whether the download is in progress. The value can be
BINDSTATUS_BEGINDOWNLOADCOMPONENTS
, BINDSTATUS_INSTALLINGCOMPONENTS
, or BINDSTATUS_ENDDOWNLOADCOMPONENTS
.
szStatusText
- is a string suitable for using in UI, if you want to take what IE gives you. This text is pretty bare-bones, and you'll probably want to use something more substantial for your progress UI. Note that technically, this parameter may be NULL, so be sure to check the value before using it.
OnProgress()
returns S_OK
to tell IE to keep downloading, or E_ABORT
to abort the download.
The ATL Way
If you have looked through the MSDN docs a bit, you may have seen that ATL has a CBindStatusCallback
class. This class implements IBindStatusCallback
for you. When using CBindStatusCallback
, you provide ATL an object that has a couple of member functions that ATL will call back as the download proceeds. The object is given to ATL as the template parameter "T" in CBindStatusCallback<T>
.
Using this class involves more work, however, since you must provide a function that stores the incoming data. When you use URLDownloadToFile()
, the data is saved for you automatically.
The Sample Project
The screen shot at the beginning of the article is from the sample project's app. You enter the URL of the file you want to download, and the full path of the target file on your system, and click Start. You can also enter a timeout in seconds, and the app will abort the download if that length of time passes before the donwload is complete.
You can find the latest updates to this any my other articles at http://home.inreach.com/mdunn/code/