/// 操作一个文件的时候,要重新执行 curl_easy_init 和 curl_easy_cleanup
/// 否则第二个文件之后的的取文件长度和下载会失败
HRESULT CTask::Download(std::string & strFirstFile, std::string & strSecondFile)
{
USES_CONVERSION;
CDlProcess dlProcess;
CURLcode recode;
CURL * pCurl = NULL;
int iSleepCnt = 0;
int iTaskCnt = 0;
double fFileSize = 0;
/// 整个进程中, 只执行一次
/// @todo 这个在函数外面做
if (!g_bCurlInit)
{
curl_global_init(CURL_GLOBAL_WIN32);
g_bCurlInit = TRUE;
}
/// 每下载一个文件, 需要执行一对 curl_easy_init(),curl_easy_cleanup
if (!strFirstFile.empty())
{
pCurl = curl_easy_init();
if (NULL == pCurl)
return S_FALSE;
fFileSize = ReturnFileLength(pCurl, strFirstFile);
dlProcess.SetFileSize(fFileLength); ///< 向所有者汇报下载进度时用的
/// 下载前,将本地已经存在的要保存的本地文件删除
/// @todo g_strFirstFile_Local 是随函数入参传进来的
ns_base::DeleteFilePro(A2W(g_strFirstFile_Local.c_str()));
if ((fFileLength > 0)
&& (dlProcess.OpenFileToWrite(g_strFirstFile_Local.c_str())))
{
curl_easy_setopt(pCurl, CURLOPT_URL, strFirstFile.c_str());
curl_easy_setopt(pCurl, CURLOPT_NOSIGNAL, 1L);
/// C++方式的回调
dlProcess.SetParentHWND(g_hParentHandle);
dlProcess.SetCUrl(pCurl);
curl_easy_setopt(pCurl, CURLOPT_WRITEDATA, &dlProcess);
curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION, &CDlProcess::CallBackProc_WriteFileFromDownLoad);
recode = curl_easy_perform(pCurl);
curl_easy_setopt(pCurl, CURLOPT_NOSIGNAL, 0L); ///< 复原参数
dlProcess.CloseFile();
}
curl_easy_cleanup(pCurl); ///< !
///< @todo 返回的是 recode 相关的结果
::PostMessageW(g_hParentHandle, WM_DL_FIRST_FILE_OK, 0, 0);
}
pCurl = curl_easy_init(); ///< 换了一个远程文件, 需要重新执行初始化
if (NULL == pCurl)
return S_FALSE;
/// 正式下载前, 得到远程文件size
/// @todo 可以将操作每一个远程文件的操作封装成一个函数
fFileLength = ReturnFileLength(pCurl, strSecondFile);
dlProcess.SetFileSize(fFileLength);
/// 下载前,将本地已经存在的要保存的本地文件删除
ns_base::DeleteFilePro(A2W(g_strSecondFile_Local.c_str()));
if ((fFileLength > 0)
&& dlProcess.OpenFileToWrite(g_strSecondFile_Local.c_str()))
{
curl_easy_setopt(pCurl, CURLOPT_URL, strSecondFile.c_str());
curl_easy_setopt(pCurl, CURLOPT_NOSIGNAL, 1L);
/// C++方式的回调
dlProcess.SetParentHWND(g_hParentHandle); ///< g_hParentHandle 随参数传进来的
dlProcess.SetCUrl(pCurl);
curl_easy_setopt(pCurl, CURLOPT_WRITEDATA, &dlProcess);
curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION, &CDlProcess::CallBackProc_WriteFileFromDownLoad);
recode = curl_easy_perform(pCurl);
curl_easy_setopt(pCurl, CURLOPT_NOSIGNAL, 0L); ///< 复原参数
curl_easy_cleanup(pCurl);
dlProcess.CloseFile();
///< @todo 返回的是 recode 相关的结果
::PostMessageW(g_hParentHandle, WM_DL_SECOND_FILE_OK, 0, 0);
}
return S_OK; ///< @todo 返回的是 recode 相关的结果
}
// return file size
double CTask::ReturnFileLength(CURL* pCurl, string strURL)
{
if (strURL.empty())
return 0;
double fFileLength = 0.0;
if (NULL != pCurl)
{
curl_easy_setopt(pCurl, CURLOPT_URL, strURL.c_str());
curl_easy_setopt(pCurl, CURLOPT_HEADER, 1L); //只需要header头
curl_easy_setopt(pCurl, CURLOPT_NOBODY, 1L); //不需要body
curl_easy_perform(pCurl);
curl_easy_getinfo(pCurl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &fFileLength);
///取得信息后, 将改过的参数复原
curl_easy_setopt(pCurl, CURLOPT_HEADER, 0L);
curl_easy_setopt(pCurl, CURLOPT_NOBODY, 0L);
}
if (fFileLength == -1)
fFileLength = 0.0f;
return fFileLength;
}
curl : 操作每一个文件时, 要成对执行 curl_easy_init 和 curl_easy_cleanup
于 2014-04-09 00:51:57 首次发布