URLDownloadToFile是urlmon.dll提供的网络操作API,可以用于从指定的URL下载文件到本地,在C++中通过类很容易实现下载进度的获取,今天需要在C语言中使用到这个函数,这里记录一下使用方法。该函数的定义如下所示。
HRESULT URLDownloadToFile(
LPUNKNOWN pCaller,
LPCTSTR szURL,
LPCTSTR szFileName,
_Reserved_ DWORD dwReserved,
LPBINDSTATUSCALLBACK lpfnCB
);
参数pCaller跟ActiveX和COM有关,如有兴趣参考
参数szURL为下载地址,地址的协议必须要是IE浏览器所支持的
参数szFileName为文件最终的保存路径,例如C:/a.txt
参数dwReserved保留,始终为0
参数lpfnCB是一个IBindStatusCallback指针。
在urlmon.h头文件的定义中,C语言风格的接口定义如下:
typedef struct IBindStatusCallbackVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
__RPC__in IBindStatusCallback * This,
/* [in] */ __RPC__in REFIID riid,
/* [annotation][iid_is][out] */
_COM_Outptr_ void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
__RPC__in IBindStatusCallback * This);
ULONG ( STDMETHODCALLTYPE *Release )(
__RPC__in IBindStatusCallback * This);
HRESULT ( STDMETHODCALLTYPE *OnStartBinding )(
__RPC__in IBindStatusCallback * This,
/* [in] */ DWORD dwReserved,
/* [in] */ __RPC__in_opt IBinding *pib);
HRESULT ( STDMETHODCALLTYPE *GetPriority )(
__RPC__in IBindStatusCallback * This,
/* [out] */ __RPC__out LONG *pnPriority);
HRESULT ( STDMETHODCALLTYPE *OnLowResource )(
__RPC__in IBindStatusCallback * This,
/* [in] */ DWORD reserved);
HRESULT ( STDMETHODCALLTYPE *OnProgress )(
__RPC__in IBindStatusCallback * This,
/* [in] */ ULONG ulProgress,
/* [in] */ ULONG ulProgressMax,
/* [in] */ ULONG ulStatusCode,
/* [unique][in] */ __RPC__in_opt LPCWSTR szStatusText);
HRESULT ( STDMETHODCALLTYPE *OnStopBinding )(
__RPC__in IBindStatusCallback * This,
/* [in] */ HRESULT hresult,
/* [unique][in] */ __RPC__in_opt LPCWSTR szError);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *GetBindInfo )(
IBindStatusCallback * This,
/* [out] */ DWORD *grfBINDF,
/* [unique][out][in] */ BINDINFO *pbindinfo);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *OnDataAvailable )(
IBindStatusCallback * This,
/* [in] */ DWORD grfBSCF,
/* [in] */ DWORD dwSize,
/* [in] */ FORMATETC *pformatetc,
/* [in] */ STGMEDIUM *pstgmed);
HRESULT ( STDMETHODCALLTYPE *OnObjectAvailable )(
__RPC__in IBindStatusCallback * This,
/* [in] */ __RPC__in REFIID riid,
/* [iid_is][in] */ __RPC__in_opt IUnknown *punk);
END_INTERFACE
} IBindStatusCallbackVtbl;
interface IBindStatusCallback
{
CONST_VTBL struct IBindStatusCallbackVtbl *lpVtbl;
};
这里的interface在C语言中的定义为struct, IBindStatusCallback回调实际上就是一个结构体,结构体只有一个字段IBindStatusCallbackVtbl *指针,你需要做的就是对这个结构体内的IBindStatusCallbackVtbl 指针进行实例化。IBindStatusCallbackVtbl 结构中包含了一系列的函数指针,也就是用于URLDownloadToFile下载时的回调函数。若要实现下载进度的获取,只需要在OnProgress回调中处理即可。
控制台示例代码
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#pragma comment(lib,"urlmon")
HRESULT (STDMETHODCALLTYPE QueryInterface)(
IBindStatusCallback* This,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void** ppvObject)
{
return E_NOTIMPL;
}
ULONG (STDMETHODCALLTYPE AddRef)(
IBindStatusCallback* This)
{
return E_NOTIMPL;
}
ULONG (STDMETHODCALLTYPE Release)(
IBindStatusCallback* This)
{
return E_NOTIMPL;
}
HRESULT (STDMETHODCALLTYPE OnStartBinding)(
IBindStatusCallback* This,
/* [in] */ DWORD dwReserved,
/* [in] */ IBinding* pib)
{
return E_NOTIMPL;
}
HRESULT (STDMETHODCALLTYPE GetPriority)(
IBindStatusCallback* This,
/* [out] */ LONG* pnPriority)
{
return E_NOTIMPL;
}
HRESULT (STDMETHODCALLTYPE OnLowResource)(
IBindStatusCallback* This,
/* [in] */ DWORD reserved)
{
return E_NOTIMPL;
}
HRESULT (STDMETHODCALLTYPE OnProgress)(
IBindStatusCallback* This,
/* [in] */ ULONG ulProgress,
/* [in] */ ULONG ulProgressMax,
/* [in] */ ULONG ulStatusCode,
/* [in] */ LPCWSTR szStatusText)
{
if (ulProgress == 0) {
return S_OK;
}
printf("%d / %d bytes , %.2f%%\n",
ulProgress, ulProgressMax,100*(double)ulProgress/(double)ulProgressMax);
return S_OK;
}
HRESULT (STDMETHODCALLTYPE OnStopBinding)(
IBindStatusCallback* This,
/* [in] */ HRESULT hresult,
/* [unique][in] */ LPCWSTR szError)
{
return E_NOTIMPL;
}
HRESULT (STDMETHODCALLTYPE GetBindInfo)(
IBindStatusCallback* This,
/* [out] */ DWORD* grfBINDF,
/* [unique][out][in] */ BINDINFO* pbindinfo)
{
return E_NOTIMPL;
}
HRESULT (STDMETHODCALLTYPE OnDataAvailable)(
IBindStatusCallback* This,
/* [in] */ DWORD grfBSCF,
/* [in] */ DWORD dwSize,
/* [in] */ FORMATETC* pformatetc,
/* [in] */ STGMEDIUM* pstgmed)
{
return E_NOTIMPL;
}
HRESULT (STDMETHODCALLTYPE OnObjectAvailable)(
IBindStatusCallback* This,
/* [in] */ REFIID riid,
/* [iid_is][in] */ IUnknown* punk)
{
return E_NOTIMPL;
}
int main(int argc,char * argv[]) {
char path[MAX_PATH];
char downloadURL[] ="https://down.qq.com/qqweb/PCQQ/PCQQ_EXE/PCQQ2020.exe";
IBindStatusCallback callBack;
IBindStatusCallbackVtbl vtbl;
vtbl.QueryInterface = QueryInterface;
vtbl.AddRef = AddRef;
vtbl.Release = Release;
vtbl.OnStartBinding = OnStartBinding;
vtbl.GetPriority = GetPriority;
vtbl.OnLowResource = OnLowResource;
vtbl.OnProgress = OnProgress;//进度回调操作
vtbl.OnStopBinding = OnStopBinding;
vtbl.GetBindInfo = GetBindInfo;
vtbl.OnDataAvailable = OnDataAvailable;
vtbl.OnObjectAvailable = OnObjectAvailable;
callBack.lpVtbl = &vtbl;
GetTempPath(sizeof(path),path);
strcat(path, "tmpqq.exe");
printf("保存位置: %s\n", path);
URLDownloadToFile(NULL,downloadURL, path,0,&callBack);
return 0;
}
扫码领个红包作为打赏吧~~
(余额宝支付时可抵现)
赏
喜欢 (2)or分享 (0)