curl : 操作每一个文件时, 要成对执行 curl_easy_init 和 curl_easy_cleanup

来源:互联网 发布:switch case用法 java 编辑:程序博客网 时间:2024/05/01 16:32
/// 操作一个文件的时候,要重新执行 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 sizedouble 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;}

0 0