关键部分代码如下:
#include "curl.h"#pragma comment(lib, "libcurl.lib")size_t CROS_DownloadDlg::getContentLengthFunc(void * ptr, size_t size, size_t nmemb, void * stream){LONGLONG len = 0;int r = sscanf((const char *)ptr, "Content-Length:%I64d\n",&len);if(r)*((LONGLONG *) stream) = len;return size * nmemb;}//根据URL获取下载文件大小LONGLONG CROS_DownloadDlg::getDownloadFileSize(const char* url){double lensize = 0.0;for(int iTry = 0 ; iTry < 3 ; iTry ++)//由于curl_easy_perform可能会有偶发性的 CURLE_WRITE_ERROR错误,所以添加重试机制{CURL *handle = curl_easy_init();curl_easy_setopt(handle, CURLOPT_URL, url);curl_easy_setopt(handle, CURLOPT_HEADER, 1);curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1);curl_easy_setopt(handle, CURLOPT_NOBODY, 1);CURLcode res = curl_easy_perform(handle), resGetInfo = CURLE_OK;if (res == CURLE_OK) {resGetInfo = curl_easy_getinfo(handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &lensize);if(CURLE_OK == resGetInfo){curl_easy_cleanup(handle);return (LONGLONG)lensize;}}curl_easy_cleanup(handle);Sleep(200);}return 0;}size_t CROS_DownloadDlg::downLoadPackage(void *ptr, size_t size, size_t nmemb, void *userdata){if(!ptr || !userdata)return 0;return fwrite(ptr, size, nmemb, (FILE *)userdata);}int CROS_DownloadDlg::assetsManagerProgressFunc(void *ptr, double totalToDownload, double nowDownloaded, double totalToUpLoad, double nowUpLoaded){if(m_bStop)return -1;if(totalToDownload > 0.0){CROS_DownloadDlg* pDlg = (CROS_DownloadDlg*)ptr;pDlg->m_lProcessSize = (LONGLONG)nowDownloaded;pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 1, 0);}return 0;}/*0 设置总大小1 设置当前下载2 下载完成3 用户停止下载,其他异常终止下载4 网络问题引发的下载异常5 设备断开连接6 磁盘剩余空间不足*/UINT CROS_DownloadDlg::DownloadProc(LPVOID lpParam){//////////////////////////////////////////////////////////////////////////使用CURL实现下载string sURL = CStringConverter::Unicode2Ansi(strURL.GetString()), sSavePath = CStringConverter::Unicode2Ansi(strSavePath.GetString());LONGLONG local_file_len = GetFileSize(strSavePath);pDlg->m_lLocalFileCurSize = local_file_len;curl_global_init(CURL_GLOBAL_DEFAULT);LONGLONG remote_file_len = getDownloadFileSize(sURL.c_str());if(!remote_file_len){pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 4, 0);//网络问题获取失败return 0;}pDlg->m_lTotalSize = remote_file_len;pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 0, 0);if(local_file_len == remote_file_len){pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 2, 0);return 0;}//得到准确大小后应判断strSavePath空间是否足够先if(remote_file_len >= (pDlg->m_ulDiskSpaceMax)){pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 6, 0);return 0;}FILE *fp = fopen(sSavePath.c_str(), "ab+");if(!fp){pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 3, 0);return 0;}LONGLONG filesize = 0;m_pCurl = curl_easy_init();//curl初始化CURLcode res;curl_easy_setopt(m_pCurl, CURLOPT_URL, sURL.c_str());//设定curl的链接curl_easy_setopt(m_pCurl, CURLOPT_CONNECTTIMEOUT,5);//设置连接超时,单位秒curl_easy_setopt(m_pCurl, CURLOPT_HEADERFUNCTION,getContentLengthFunc);curl_easy_setopt(m_pCurl, CURLOPT_HEADERDATA, &filesize);curl_easy_setopt(m_pCurl, CURLOPT_RESUME_FROM_LARGE, local_file_len);//断点下载设置curl_easy_setopt(m_pCurl, CURLOPT_WRITEFUNCTION, downLoadPackage);curl_easy_setopt(m_pCurl, CURLOPT_WRITEDATA, fp);//设置将data写入到文件流fp中curl_easy_setopt(m_pCurl, CURLOPT_FOLLOWLOCATION, 1L);//设置重定位URL,使用自动跳转,返回的头部中有Location(一般直接请求的url没找到),则继续请求Location对应的数据curl_easy_setopt(m_pCurl, CURLOPT_MAXREDIRS,5);//查找次数,防止查找太深curl_easy_setopt(m_pCurl, CURLOPT_NOPROGRESS, false);//设为false 下面才能设置进度响应函数curl_easy_setopt(m_pCurl, CURLOPT_PROGRESSFUNCTION, assetsManagerProgressFunc);//进度响应函数curl_easy_setopt(m_pCurl, CURLOPT_PROGRESSDATA, pDlg);//数据传输的对象curl_easy_setopt(m_pCurl, CURLOPT_VERBOSE,1L);res = curl_easy_perform(m_pCurl);curl_easy_cleanup(m_pCurl);curl_global_cleanup();m_pCurl = NULL;if (res != CURLE_OK){fclose(fp);if(res == CURLE_ABORTED_BY_CALLBACK)//点击停止下载pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 3, 0);else if(res == CURLE_RECV_ERROR)//断网 /* 56 - failure in receiving network data */pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 4, 0);elsepDlg->SendMessage(WM_DOWNLOADPROC_MSG, 3, 0);return 0;}fclose(fp);pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 2, 0);return 0;}void CROS_DownloadDlg::OnClickBtnStop(){if(m_pCurl){curl_easy_pause(m_pCurl, CURLPAUSE_RECV);if(IDYES == ShowMessage(IDS_DEF_ROS_SURE_TO_STOP, CiPhoneUtil::GetApplicationName(), SM_ICON_QUESTION|SM_YES_AND_NO)){m_btnStop.EnableWindow(FALSE);m_bStop = true;return;}curl_easy_pause(m_pCurl, CURLPAUSE_RECV_CONT);}}

