CCurlRequest.h
#pragma once
#include <string>
#include "curl/include/curl/curl.h"
#include <windows.h>
typedef struct _CURL_XFER_PROGRESS
{
curl_off_t dlNow;
curl_off_t dlTotal;
curl_off_t ulNow;
curl_off_t ulTotal;
_CURL_XFER_PROGRESS()
{
ZeroMemory(this, sizeof(*this));
}
}CURL_XFER_PROGRESS;
class CCurlRequest
{
public:
CCurlRequest();
~CCurlRequest();
bool Get(std::string strUrl,
std::string& strResponse,
std::string strHeader = "Content-Type:application/json;charset=UTF-8"
);
bool Post(std::string strUrl,
std::string& strResponse,
const std::string& strParam,
std::string strHeader = "Content-Type:application/json;charset=UTF-8"
);
private:
bool _Initialize();
void _Uninitialize();
void _ResetProgress();
static size_t _WriteFunc(
void* pBuffer,
size_t size,
size_t nmemb,
void* pUserData
);
static int _ProgressFunc(
void* pUserData,
curl_off_t dlTotal,
curl_off_t dlNow,
curl_off_t ulTotal,
curl_off_t ulNow
);
private:
CURL* m_pCurl;
std::string m_strResponse;
CURL_XFER_PROGRESS m_dataProgress;
};
CCurlRequest.cpp
#include "CCurlRequest.h"
CCurlRequest::CCurlRequest()
:
m_pCurl(nullptr)
{
_Initialize();
}
CCurlRequest::~CCurlRequest()
{
_Uninitialize();
}
bool CCurlRequest::_Initialize()
{
if (nullptr != m_pCurl)
{
return true;
}
m_pCurl = curl_easy_init();
if (nullptr == m_pCurl)
{
return false;
}
curl_easy_setopt(m_pCurl, CURLOPT_WRITEFUNCTION, _WriteFunc); // 设置写入回调
curl_easy_setopt(m_pCurl, CURLOPT_WRITEDATA, static_cast<void*>(this)); // 设置写入回调参数
curl_easy_setopt(m_pCurl, CURLOPT_NOPROGRESS, 0L); // 设置进度回调
curl_easy_setopt(m_pCurl, CURLOPT_XFERINFOFUNCTION, _ProgressFunc); // 设置进度回调
curl_easy_setopt(m_pCurl, CURLOPT_XFERINFODATA, static_cast<void*>(this)); // 设置进度回调参数
curl_easy_setopt(m_pCurl, CURLOPT_NOSIGNAL, 1L); // 指示 libcurl 不要使用任何信号/警报处理程序,即使在使用超时时时也是如此
curl_easy_setopt(m_pCurl, CURLOPT_LOW_SPEED_LIMIT, 1L); // 设置低速限制
curl_easy_setopt(m_pCurl, CURLOPT_LOW_SPEED_TIME, 1L); // 设置低速时间
curl_easy_setopt(m_pCurl, CURLOPT_CONNECTTIMEOUT, 60); // 设置连接超时秒数
curl_easy_setopt(m_pCurl, CURLOPT_TIMEOUT, 60000); // 设置读取操作超时秒数
curl_easy_setopt(m_pCurl, CURLOPT_SSL_VERIFYPEER, 0L); // 设置我们是否应该在 ssl 握手中验证对等体
curl_easy_setopt(m_pCurl, CURLOPT_SSL_VERIFYHOST, 0L); // 设置我们是否应该从 ssl 中的对等证书中验证公用名
curl_easy_setopt(m_pCurl, CURLOPT_FOLLOWLOCATION, 1L); // 设置重定向
curl_easy_setopt(m_pCurl, CURLOPT_VERBOSE, 0L); // 设置是否打印 libcurl 执行过程
return true;
}
void CCurlRequest::_Uninitialize()
{
if (nullptr != m_pCurl)
{
curl_easy_cleanup(m_pCurl);
m_pCurl = nullptr;
}
}
void CCurlRequest::_ResetProgress()
{
m_dataProgress.dlNow = -1;
m_dataProgress.dlTotal = -1;
m_dataProgress.ulNow = -1;
m_dataProgress.ulTotal = -1;
}
size_t CCurlRequest::_WriteFunc(
void* pBuffer,
size_t size,
size_t nmemb,
void* pUserData
)
{
size_t realsize = size * nmemb;
if (NULL == pBuffer || NULL == pUserData)
{
return realsize;
}
CCurlRequest* pThis = static_cast<CCurlRequest*>(pUserData);
pThis->m_strResponse += std::string((const char*)pBuffer, realsize);
return realsize;
}
int CCurlRequest::_ProgressFunc(
void* pUserData,
curl_off_t dlTotal,
curl_off_t dlNow,
curl_off_t ulTotal,
curl_off_t ulNow
)
{
UNREFERENCED_PARAMETER(dlTotal);
UNREFERENCED_PARAMETER(dlNow);
UNREFERENCED_PARAMETER(ulTotal);
UNREFERENCED_PARAMETER(ulNow);
// 执行默认的进度函数
//return CURL_PROGRESSFUNC_CONTINUE;
CCurlRequest* pThis = static_cast<CCurlRequest*>(pUserData);
CURL_XFER_PROGRESS info;
info.dlNow = dlNow;
info.dlTotal = dlTotal;
info.ulNow = ulNow;
info.ulTotal = ulTotal;
//下载进度记录, 有变化时更新打印
if (0 != memcmp(&info, &pThis->m_dataProgress, sizeof(CURL_XFER_PROGRESS)))
{
//printf("Download: %lld / %lld Upload: %lld / %lld\n", dlNow, dlTotal, ulNow, ulTotal);
pThis->m_dataProgress = info;
}
return CURLE_OK;
}
bool CCurlRequest::Get(
std::string strUrl,
std::string& strResponse,
std::string strHeader/* = "Content-Type:application/json;charset=UTF-8"*/
)
{
CURLcode curlCode = CURLE_OK;
if (nullptr == m_pCurl)
{
return false;
}
_ResetProgress();// 重置传输进度
curl_slist* slist = curl_slist_append(NULL, strHeader.c_str()); // 添加头
curl_easy_setopt(m_pCurl, CURLOPT_URL, strUrl.c_str()); // 设置链接URL
curl_easy_setopt(m_pCurl, CURLOPT_POST, 0L); // 设置为提交数据
curl_easy_setopt(m_pCurl, CURLOPT_HTTPHEADER, slist); // 设置头
curlCode = curl_easy_perform(m_pCurl);
curl_slist_free_all(slist);
strResponse = std::move(m_strResponse);
return CURLE_OK == curlCode;
}
bool CCurlRequest::Post(
std::string strUrl,
std::string& strResponse,
const std::string& strParam,
std::string strHeader/* = "Content-Type:application/json;charset=UTF-8"*/)
{
CURLcode curlCode = CURLE_OK;
if (nullptr == m_pCurl)
{
return false;
}
_ResetProgress();// 重置传输进度
curl_slist* slist = curl_slist_append(NULL, strHeader.c_str()); // 添加头
curl_easy_setopt(m_pCurl, CURLOPT_URL, strUrl.c_str()); // 设置链接URL
curl_easy_setopt(m_pCurl, CURLOPT_POSTFIELDS, strParam.c_str()); // 设置body
curl_easy_setopt(m_pCurl, CURLOPT_POSTFIELDSIZE, strParam.size()); // 设置body长度
curl_easy_setopt(m_pCurl, CURLOPT_POST, 1L); // 设置为提交数据
curl_easy_setopt(m_pCurl, CURLOPT_HTTPHEADER, slist); // 设置头
curlCode = curl_easy_perform(m_pCurl);
curl_slist_free_all(slist);
strResponse = std::move(m_strResponse);
return CURLE_OK == curlCode;
}
main.cpp
// CurlDownload.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <tchar.h>
#include "CCurlDownloadMgr.h"
#include "ThreadPool.h"
#include "CCurlRequest.h"
#include "CStrUtils.h"
#include "CTimeUtils.h"
#define GET_URL1 R"(https://gitee.com/flame_cyclone/fcassistant-binary/releases/download/1.0.1.15/LuaExample.lua)"
#define GET_URL2 R"(https://gitee.com/flame_cyclone/fcassistant-binary/releases/download/1.0.1.15/LuaExample.lua2)"
#define POST_URL R"(https://gitee.com/flame_cyclone/fcassistant-binary/releases/download/1.0.1.15/LuaExample.lua)"
int main()
{
curl_global_init(CURL_GLOBAL_ALL);
CCurlRequest obj;
std::string strResponse;
obj.Get(GET_URL1, strResponse);
obj.Post(POST_URL, strResponse, "{}");
curl_global_cleanup();
return 0;
}