493 lines
13 KiB
C++
493 lines
13 KiB
C++
// 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;
|
|
} |