// DownloadFile.cpp: implementation of the CFileTransfer_crul class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "FileTransfer_crul.h" #include "Constant.h" #include "CtrlProtocolDef.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif extern SYSTEMTIME g_sysCurTime; extern int g_iUILanguage; ////////////////////////////////////////////////////////////////////// // Construction/Destruction /////////////////////////////z///////////////////////////////////////// DOUBLE CFileTransfer_crul::m_RecvFileSize = 0; int CFileTransfer_crul::m_nWriteFileSize = 0; CFileTransfer_crul::CFileTransfer_crul() { //curl_global_init(CURL_GLOBAL_ALL); m_pCrEasyHandl = NULL; m_pCrPuteasyHandl = NULL; //m_nWriteFileSize = 0; m_strSavePath = _T(""); m_strSaveName = _T(""); m_strUrl = _T(""); m_lTotalRecvFileSize = 0; m_lCurRecvSize = 0; // m_pDownLoadFile = NULL; m_nTimeOut = 120; m_bIsNeedProgress = false; m_bIsNeedErrInfo = false; m_bIsGobalInitial = false; m_pLog = NULL; m_bIsHttpsFlag = false; m_bIsSSLCertify = false; InitalLogInfo(); } CFileTransfer_crul::~CFileTransfer_crul() { // curl_easy_cleanup(m_pCrEasyHandl); curl_global_cleanup(); m_bIsGobalInitial = false; if (m_pLog) { fclose(m_pLog); m_pLog = NULL; } } void CFileTransfer_crul::InitalLogInfo() { if (NULL == m_pLog) { m_pLog = fopen("LOG\\filetrans_crul_log.txt","ab+"); if (NULL == m_pLog) { if (LANG_ZHCN == g_iUILanguage) AfxMessageBox(_T("打开 filetrans_crul_log.txt 失败!!")); else MessageBoxEx(NULL, _T("Open filetrans_crul_log.txt failed!!!"), STRING_MESSAGEBOXEX_TITLE, MB_OK, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)); } } } bool CFileTransfer_crul::Inital() { if (m_bIsGobalInitial) { return true; } CURLcode res; res = curl_global_init(CURL_GLOBAL_WIN32); CString strTmp = _T(""); if (CURLE_OK != res) { strTmp.Format(_T("[%d] global Inital crul failed! error_code = %d"),__LINE__, res); PrintLog(strTmp); return false; } if (LIBCURL_VERSION_NUM < 0x072000) { strTmp.Format(_T("[%d] libcrul version is low!!!, version_num = %d"), __LINE__, LIBCURL_VERSION_NUM); PrintLog(strTmp); return false; } m_bIsGobalInitial = true; return true; } void CFileTransfer_crul::UnInital() { curl_global_cleanup(); } void CFileTransfer_crul::SetOption(EnOptFlag enFlag, CString strInfo, bool bFlag) { switch (enFlag) { case OPT_URL_ADDRESS: m_strUrl = strInfo; break; case OPT_DOWNLOAD_PATH: m_strSavePath = strInfo; break; case OPT_DOWNLOAD_NAME: m_strSaveName = strInfo; break; case OPT_TIMEOUT: m_nTimeOut = atoi(strInfo.GetBuffer(0)); break; case OPT_NEED_PROGRESS: m_bIsNeedProgress = bFlag; break; case OPT_NEED_ERRORINFO: m_bIsNeedErrInfo = bFlag; break; case OPT_HTTPS_ACCESS: m_bIsHttpsFlag = bFlag; break; case OPT_SSL_CERTIFY: m_bIsSSLCertify = bFlag; break; default: CString strTmp = _T(""); strTmp.Format(_T("[%d] Unknow Opt_Flag, value = %d"), __LINE__, enFlag); PrintLog(strTmp); break; } return ; } bool CFileTransfer_crul::DownloadFile() { CString strTmp = _T(""); if (m_strUrl.IsEmpty() || m_strSaveName.IsEmpty() || m_strSavePath.IsEmpty()) { strTmp.Format(_T("[%d] Url or SaveFileInfo is not set!!!"),__LINE__); PrintLog(strTmp); return false; } if (m_bIsHttpsFlag && m_bIsSSLCertify) { if (LANG_ZHCN == g_iUILanguage) AfxMessageBox(_T("不支持协议https的ssl认证。")); else MessageBoxEx(NULL, _T("Ssl certify of protocol https is not supported."), STRING_MESSAGEBOXEX_TITLE, MB_OK, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)); return false; } if (!GetUrlResConValild()) { if (LANG_ZHCN == g_iUILanguage) AfxMessageBox(_T("下载文件失败!!")); else MessageBoxEx(NULL, _T("DownLoad file failed!!!"), STRING_MESSAGEBOXEX_TITLE, MB_OK, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)); return false; } FILE *pFile = NULL; CString strDownLoadFile = m_strSavePath + m_strSaveName; pFile = fopen(strDownLoadFile.GetBuffer(0), "wb+"); if (NULL == pFile) { strTmp.Format(_T("[%d] open file failed, errorno = %d, file_path = %s"), __LINE__, GetLastError(), strDownLoadFile.GetBuffer(0)); //AfxMessageBox(strTmp.GetBuffer(0)); PrintLog(strTmp); return false; } m_pCrEasyHandl = curl_easy_init(); if (NULL == m_pCrEasyHandl) { strTmp.Format(_T("[%d] curl_easy_init failed!!!"), __LINE__); PrintLog(strTmp); return false; } STWriteInfo stWriteInfo; stWriteInfo.pFile = pFile; stWriteInfo.pFileTrans = (void *)this; char chErrorInfo[CURL_ERROR_SIZE]; memset(chErrorInfo, 0, sizeof(chErrorInfo)); long nOnOff = (true == m_bIsNeedProgress) ? 0 : 1; // struct curl_slist *headers=NULL; // headers = curl_slist_append(headers, "Pragma:no-cache"); // headers = curl_slist_append(headers, "Cache-Control:max-age=0"); // headers = curl_slist_append(headers, "Cache-Control: no-cache"); // headers = curl_slist_append(headers, "Cache-Control: max-age=0"); // headers = curl_slist_append(headers, "Cache-Control: no-store"); CURLcode resSetOpt; //设置可选项 // resSetOpt = curl_easy_setopt(m_pCrEasyHandl, CURLOPT_HTTPHEADER, headers); resSetOpt = curl_easy_setopt(m_pCrEasyHandl, CURLOPT_URL, m_strUrl.GetBuffer(0)); resSetOpt = curl_easy_setopt(m_pCrEasyHandl, CURLOPT_TIMEOUT, m_nTimeOut); resSetOpt = curl_easy_setopt(m_pCrEasyHandl, CURLOPT_WRITEDATA, &stWriteInfo); resSetOpt = curl_easy_setopt(m_pCrEasyHandl, CURLOPT_WRITEFUNCTION, &WriteToFile); resSetOpt = curl_easy_setopt(m_pCrEasyHandl, CURLOPT_NOPROGRESS, nOnOff); resSetOpt = curl_easy_setopt(m_pCrEasyHandl, CURLOPT_ERRORBUFFER, chErrorInfo);//设置错误信息 resSetOpt = curl_easy_setopt(m_pCrEasyHandl, CURLOPT_VERBOSE, 1); if (m_bIsNeedProgress) { resSetOpt = curl_easy_setopt(m_pCrEasyHandl, CURLOPT_XFERINFOFUNCTION, xferinfo); resSetOpt = curl_easy_setopt(m_pCrEasyHandl, CURLOPT_XFERINFODATA, this); } //取消SSL验证 if (m_bIsHttpsFlag && !m_bIsSSLCertify) { resSetOpt = curl_easy_setopt(m_pCrEasyHandl, CURLOPT_SSL_VERIFYPEER, 0L); } strTmp.Empty(); strTmp.Format(_T("[%d] url = %s, timeout = %d, show_progress = %d"), __LINE__, m_strUrl.GetBuffer(0), m_nTimeOut, m_bIsNeedProgress); PrintLog(strTmp); //show progress m_nWriteFileSize = 0; CURLcode resCode = curl_easy_perform(m_pCrEasyHandl); // curl_slist_free_all(headers); if (CURLE_OK != resCode) { strTmp.Empty(); if (LANG_ZHCN == g_iUILanguage) { strTmp.Format(_T("下载文件失败,请检查网络环境.")); AfxMessageBox(strTmp.GetBuffer(0)); } else { strTmp.Format(_T("Download failed, please check the network environment.")); MessageBoxEx(NULL, strTmp, STRING_MESSAGEBOXEX_TITLE, MB_OK, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)); } strTmp.Empty(); strTmp.Format(_T("[%d]Download failed, excute easy_perform failed!!!, return_code = %d, error_msg = %s"), __LINE__, resCode, chErrorInfo); PrintLog(strTmp); } // else // { // if (0 == m_nWriteFileSize) // { // // AfxMessageBox(_T("download file failed!")); // strTmp.Empty(); // strTmp.Format(_T("[%d] excute easy_perform ok,but Dst_File_Length is 0!"),__LINE__); // PrintLog(strTmp); // resCode = CURLE_REMOTE_FILE_NOT_FOUND;; // // // } // } fclose(pFile); pFile = NULL; curl_easy_cleanup(m_pCrEasyHandl); return (CURLE_OK == resCode) ? true : false; } size_t CFileTransfer_crul::WriteToFile(void *ptr, size_t size, size_t nmemb, void *userp) { STWriteInfo* pWriteInfo = (STWriteInfo*)userp; size_t szRes = fwrite(ptr, size, nmemb, pWriteInfo->pFile); m_nWriteFileSize += szRes; if (szRes == size * nmemb) { return szRes; } else { CString strTmp = _T(""); CFileTransfer_crul* pFileTrans = (CFileTransfer_crul*)pWriteInfo->pFileTrans; if (0 == szRes) { strTmp.Format(_T("[%d] write File failed!, FileName = %s, errorno = %d"),__LINE__, pFileTrans->m_strSaveName.GetBuffer(0), GetLastError()); } else { strTmp.Format(_T("[%d] writed bytes is not equal to received bytes! FileName = %s, Writed_number = %d, Received_number = %d"), __LINE__, pFileTrans->m_strSaveName.GetBuffer(0), szRes, size * nmemb); } pFileTrans->PrintLog(strTmp); return szRes; } } DOUBLE CFileTransfer_crul::GetFileSize() { CURL *curl; CURLcode res; DOUBLE FileSize=0; curl = curl_easy_init(); if(curl) { // struct curl_slist *headers=NULL; // headers = curl_slist_append(headers, "Cache-Control: no-cache"); // headers = curl_slist_append(headers, "Cache-Control: max-age=0"); // headers = curl_slist_append(headers, "Cache-Control: no-store"); // curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_URL, m_strUrl); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 120); curl_easy_setopt(curl, CURLOPT_HEADER, 1); curl_easy_setopt(curl, CURLOPT_NOBODY, 1); res = curl_easy_perform(curl); // curl_slist_free_all(headers); if(res != CURLE_OK) return FALSE; res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &FileSize); if(res != CURLE_OK) return FALSE; curl_easy_cleanup(curl); } return FileSize; } bool CFileTransfer_crul::GetUrlResConValild() { CURL *curl; CURLcode res; DOUBLE FileSize=0; curl = curl_easy_init(); CString strLog = _T(""); int iTest = 1; if(curl) { char chErrInfo[CURL_ERROR_SIZE]; memset(chErrInfo, 0, sizeof(chErrInfo)); // struct curl_slist *headers=NULL; // headers = curl_slist_append(headers, "Cache-Control: no-cache"); // headers = curl_slist_append(headers, "Cache-Control: max-age=0"); // headers = curl_slist_append(headers, "Cache-Control: no-store"); // curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_URL, m_strUrl); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10); curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); curl_easy_setopt(curl, CURLOPT_HEADER, 1); curl_easy_setopt(curl, CURLOPT_NOBODY, 1); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &iTest); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteFuncForUrlTest); curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, chErrInfo);//设置错误信息 //为了防止偶尔报无法解析网站的问题,在这里只使用IPV4进行DNS的解析 curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); //temp 临时版本,添加重试功能,次数为3 int iTimes = 3; while(iTimes > 0) { res = curl_easy_perform(curl); if (res == CURLE_OK) break; iTimes--; } if(res != CURLE_OK) { //此时如果错误原因是Failed writing body,代表回调函数返回值和回调函数传入的大小不一致,则会引起中断,并报错 //如果没有设置回调函数,则会用默认的回调函数代替,默认的回调函数是将数据写入到标准的输入出里去 strLog.Format(_T("[%d]GetUrlResContent::excute curl_perform 3 times failed!,errmsg = %s,url = %s"),__LINE__ ,chErrInfo,m_strUrl); PrintLog(strLog); curl_easy_cleanup(curl); return false; } long retCode = 0; res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE , &retCode); //如果返回200,则说明正确的找到了网址 if ((CURLE_OK == res) && (200 == retCode)) { curl_easy_cleanup(curl); return true; } strLog.Format(_T("[%d]GetUrlResConValild::get_crul_info failed, resCode = %d, ResponseCode = %d, ErrorMSg = %s, url = %s"), __LINE__, res, retCode, chErrInfo, m_strUrl); PrintLog(strLog); curl_easy_cleanup(curl); return false; } strLog.Format(_T("[%d]GetUrlResConValild:: crul inital failed!!!"),__LINE__); PrintLog(strLog); return false; } VOID CFileTransfer_crul::SetRecvSize(size_t f_size) { m_RecvFileSize += f_size; } // BOOL CFileTransfer_crul::GetFileList(char *f_buff) // { // CURL *curl; // CURLcode res; // DOUBLE FileSize; // // curl = curl_easy_init(); // // if(curl) // { // curl_easy_setopt(curl, CURLOPT_URL, m_strUrl); // curl_easy_setopt(curl, CURLOPT_TIMEOUT, 120); // curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)f_buff); // curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteToBuff); // // res = curl_easy_perform(curl); // // if(res != CURLE_OK) // return FALSE; // // curl_easy_cleanup(curl); // // } //} size_t CFileTransfer_crul::WriteToBuff(void *ptr, size_t size, size_t nmemb, void *userp) { memcpy((char *)userp, ptr, (size * nmemb)); return size * nmemb; } int CFileTransfer_crul::xferinfo(void *p, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) { CFileTransfer_crul* pFileTrans = (CFileTransfer_crul*)p; pFileTrans->m_lTotalRecvFileSize = dltotal; pFileTrans->m_lCurRecvSize = dlnow; return 0; } void CFileTransfer_crul::PrintLog(CString strLog) { if (NULL == m_pLog) { MessageBox(NULL, "can't write fileTransfer_crul_log, log File point is NULL", "LOG_ERROR", MB_OK); return; } CString strOutPut = _T(""); strOutPut.Format(_T("%04d-%02d-%02d %02d:%02d:%02d.%03d %s \r\n"),g_sysCurTime.wYear, g_sysCurTime.wMonth, g_sysCurTime.wDay, g_sysCurTime.wHour, g_sysCurTime.wMinute, g_sysCurTime.wSecond, g_sysCurTime.wMilliseconds, strLog.GetBuffer(0)); fwrite(strOutPut.GetBuffer(0), 1, strOutPut.GetLength(), m_pLog); fflush(m_pLog); } size_t CFileTransfer_crul::WriteFuncForUrlTest(void *ptr, size_t size, size_t nmemb, void *userp) { return size * nmemb; }