本文配套程序下载地址为: http://pan.baidu.com/share/link?shareid=358034&uk=3995556177
下载地址获得了,那就下载吧。最简单的,URLDownloadToFile。如何显示进度呢?URLDownloadToFile提供了一个回调,实现这个回调就可以了
STDMETHODIMP CDownloadFileByHttp::OnProgress(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
{
m_eaz->downloadBytes = ulProgress;
return S_OK;
}
解决了!
但问题又来了,一个镜像2.2G,下载速度200K,要下载3个小时!体验也太差了些。我用迅雷试了一下,可以达到1.4M!看来需要多线程下载啊。
怎么多线程呢?解决方法有两个,一个是像迅雷一样对单个文件多线程下载,这需要服务器支持。另外一个就是讲镜像文件分割,然后同时下载多个小文件。第二个方法有个好处,就是如果中途程序退出了,已经下载的完整文件不需要再下载了。所以选择第二种方法。
于是又改代码,开了5个线程,同时下载5个文件。但是奇怪的是,只有两个文件同时下载。超过两个URLDownloadToFile就返回错误。不解。google一下,原来是ie的限制。ie缺省就只能同时下载2个。晕。怎么办呢?修改ie设置?可是ie版本那么多,都要去改很麻烦。而且修改ie设置的时候估计360又得弹框了,改也改不了。怎么办呢?
又google。找到迅雷sdk库,将sdk集成进来后,安装包大了0.5M,可实验了一下,效果不理想。因为下载单个文件的时候,迅雷sdk是单线程下载,根本不会提高下载速度,而且必须要安装迅雷。另外在托盘处会弹出下载速度,可是速度经常不更新,不靠谱。
于是又google,这下找到一个下载库,libcurl。看了一下例子,调用起来很简单。而且multithread例子很适合,就把这个例子改了改,集成到程序里面去,效果很好。推荐以后下载就用这个库,而且稍稍将multithread例子改一下,就可以支持多线程下载一个文件。
size_t CDownloadFileByHttp::write_data(void *ptr, size_t size, size_t nmemb, void *stream)
{
CDownloadFileByHttp *htt = (CDownloadFileByHttp *)stream;
size_t written = fwrite(ptr, size, nmemb, htt->m_pagefile);
htt->m_eaz->downloadBytes += written;
return written;
}
BOOL CDownloadFileByHttp::DownloadFile()
{
BOOL ret = FALSE;
CStringA aurl = CW2A(m_url);
CURL *curl;
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, aurl.GetBuffer()); aurl.ReleaseBuffer();
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &CDownloadFileByHttp::write_data);
CStringA afile = CW2A(m_downloadFilePath);
m_pagefile = fopen(afile.GetBuffer(), "wb"); afile.ReleaseBuffer();
if (m_pagefile)
curl_easy_setopt(curl, CURLOPT_FILE, this);
else
goto RETURN;
int i = 0;
while ( i < 5 )
{
if (0 == curl_easy_perform(curl))
{
m_status = DOWNLOADED;
m_eaz->status = DOWNLOADED;
m_eaz->downloadBytes = m_eaz->size;
TheDownloadManagerHelper.OneFileDownloaded(m_eaz);
LOGEx(L"一个文件下载完成: " + m_downloadFilePath);
ret = TRUE;
goto RETURN;
}
else
{
CString msg;
msg.Format(L"Error: Http下载文件失败, file = %s, errorcode = %d", m_downloadFilePath.GetBuffer(), GetLastError());
m_downloadFilePath.ReleaseBuffer();
LOGEx(msg);
m_eaz->downloadBytes = 0;
i++;
}
}
m_eaz->status = NOT_DOWNLOAD;
LOGEx(L"Error: Http下载文件失败: " + m_downloadFilePath);
TheDownloadManagerHelper.m_errorCode = -7; // Http下载文件失败
RETURN:
curl_easy_cleanup(curl);
if (m_pagefile)
fclose(m_pagefile);
return ret;
}
跑了一下,速度达到了1.4M,和迅雷一样! 好高兴,哈哈