curl 一个使用例子
#include <iostream> #define Main main #include <string> #include <assert.h> #include <curl/curl.h> #include <curl/easy.h> #pragma comment(lib,"libcurl.lib") #pragma comment(lib,"ws2_32.lib") using namespace std; class CLibcurlCallback { public: virtual void Progress(void* lpParam, double dTotal, double bLoaded) = 0; }; enum LibcurlFlag { Lf_None = 0, Lf_Download, Lf_Post, Lf_Get, }; class CLibcurl { public: CLibcurl(void); ~CLibcurl(void); /****************************************************************************** *封装类的外部调用接口 */ bool SetPorts(LONG port); //设置连接端口号 bool SetTimeout(int nSecond); //设置执行超时(秒) bool SetConnectTimeout(int nSecond); //设置连接超时(秒) bool SetUserAgent(LPCSTR lpAgent); //设置用户代理 bool SetResumeFrom(LONG lPos); //设置断点续传起始位置 bool SetResumeFromLarge(LONGLONG llPos); //设置断点续传起始位置,针对大文件 bool AddHeader(LPCSTR lpKey, LPCSTR lpValue); //添加自定义头 void ClearHeaderList(); //清理HTTP列表头 bool SetCookie(LPCSTR lpCookie); //设置HTTP请求cookie bool SetCookieFile(LPCSTR lpFilePath); //设置HTTP请求cookie文件 const char* GetError()const; //获取错误详细信息 void SetCallback(CLibcurlCallback* pCallback, void* lpParam); //设置下载进度回调 bool DownloadToFile(LPCSTR lpUrl, LPCSTR lpFile); //下载文件到磁盘 bool Post(LPCSTR lpUrl, LPCSTR lpData); //Post 字符串数据 bool Post(LPCSTR lpUrl, unsigned char* lpData, unsigned int nSize); //Post 字符串或者二进制数据 bool Get(LPCSTR lpUrl); //Get 请求 const string& GetRespons()const; //获取Post/Get请求返回数据 const char* GetResponsPtr()const; //获取Post/Get请求返回数据 protected: static size_t WriteCallback(void* pBuffer, size_t nSize, size_t nMemByte, void* pParam); static size_t HeaderCallback(void* pBuffer, size_t nSize, size_t nMemByte, void* pParam); static int ProgressCallback(void *pParam, double dltotal, double dlnow, double ultotal, double ulnow); private: CURL *m_pCurl; LONG m_nPort; HANDLE m_hFile; CURLcode m_curlCode; string m_strRespons; LibcurlFlag m_lfFlag; curl_slist *m_curlList; void *m_pCallbackParam; CLibcurlCallback *m_pCallback; }; class CLibcurlCallbackEx : public CLibcurlCallback { public: virtual void Progress(void* lpParam, double dTotal, double dLoaded) { if (dTotal == 0.0) return; double bPercent = (dLoaded / dTotal) * 100; printf("下载进度:%0.2lf%%\n", bPercent); } }; class CommonTools { public: CommonTools() {} ~CommonTools() {} public: static size_t receive_data(void *contents, size_t size, size_t nmemb, void *stream); // HTTP 下载文件的回掉函数 static size_t writedata2file(void *ptr, size_t size, size_t nmemb, FILE *stream); // 文件下载接口 static int download_file(const char* url, const char outfilename[FILENAME_MAX]); // http get 请求 static CURLcode HttpGet(const std::string & strUrl, std::string & strResponse, int nTimeout); // htpp post 请求 static CURLcode HttpPost(const std::string & strUrl, std::string szJson, std::string & strResponse, int nTimeout); }; int Main() { //string url("http://t.weather.sojson.com/api/weather/city/101270101"); //string buf; //CommonTools::HttpGet(url, buf, 300); //FILE *File = NULL; //fopen_s(&File, "test.json", "wb+"); //if (File) //{ // fwrite(buf.c_str(), buf.length(), 1, File); //} //fclose(File); //File = NULL; system("pause"); return 0; } CLibcurl::CLibcurl(void) : m_pCurl(NULL) , m_nPort(80) , m_hFile(INVALID_HANDLE_VALUE) , m_pCallback(NULL) , m_pCallbackParam(NULL) , m_curlCode(CURLE_OK) , m_lfFlag(Lf_None) , m_curlList(NULL) { m_pCurl = curl_easy_init(); curl_easy_setopt(m_pCurl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(m_pCurl, CURLOPT_WRITEDATA, this); } CLibcurl::~CLibcurl(void) { ClearHeaderList(); curl_easy_cleanup(m_pCurl); if (m_hFile != INVALID_HANDLE_VALUE) { CloseHandle(m_hFile); } } bool CLibcurl::SetPorts(LONG port) { if (port == m_nPort) return true; m_nPort = port; m_curlCode = curl_easy_setopt(m_pCurl, CURLOPT_PORT, m_nPort); return CURLE_OK == m_curlCode; } bool CLibcurl::SetTimeout(int nSecond) { if (nSecond < 0) return false; m_curlCode = curl_easy_setopt(m_pCurl, CURLOPT_TIMEOUT, nSecond); return CURLE_OK == m_curlCode; } bool CLibcurl::SetConnectTimeout(int nSecond) { if (nSecond < 0) return false; m_curlCode = curl_easy_setopt(m_pCurl, CURLOPT_CONNECTTIMEOUT, nSecond); return CURLE_OK == m_curlCode; } bool CLibcurl::SetUserAgent(LPCSTR lpAgent) { if (NULL == lpAgent) return false; int nLen = strlen(lpAgent); if (nLen == 0) return false; m_curlCode = curl_easy_setopt(m_pCurl, CURLOPT_USERAGENT, lpAgent); return CURLE_OK == m_curlCode; } bool CLibcurl::SetResumeFrom(LONG lPos) { if (lPos < 0) return false; m_curlCode = curl_easy_setopt(m_pCurl, CURLOPT_RESUME_FROM, lPos); return CURLE_OK == m_curlCode; } bool CLibcurl::SetResumeFromLarge(LONGLONG llPos) { if (llPos < 0) return false; m_curlCode = curl_easy_setopt(m_pCurl, CURLOPT_RESUME_FROM_LARGE, llPos); return CURLE_OK == m_curlCode; } bool CLibcurl::AddHeader(LPCSTR lpKey, LPCSTR lpValue) { assert(lpKey != NULL && lpValue != NULL); int nLen1 = strlen(lpKey), nLen2 = strlen(lpValue); assert(nLen1 > 0 && nLen2 > 0); string strHeader(lpKey); strHeader.append(": "); strHeader.append(lpValue); m_curlList = curl_slist_append(m_curlList, strHeader.c_str()); m_curlCode = curl_easy_setopt(m_pCurl, CURLOPT_HTTPHEADER, m_curlList); return CURLE_OK == m_curlCode; } void CLibcurl::ClearHeaderList() { if (m_curlList) { curl_slist_free_all(m_curlList); m_curlList = NULL; } } bool CLibcurl::SetCookie(LPCSTR lpCookie) { assert(lpCookie != NULL); m_curlCode = curl_easy_setopt(m_pCurl, CURLOPT_COOKIE, lpCookie); return CURLE_OK == m_curlCode; } bool CLibcurl::SetCookieFile(LPCSTR lpFilePath) { assert(lpFilePath != NULL); m_curlCode = curl_easy_setopt(m_pCurl, CURLOPT_COOKIEFILE, lpFilePath); return CURLE_OK == m_curlCode; } const char* CLibcurl::GetError() const { return curl_easy_strerror(m_curlCode); } void CLibcurl::SetCallback(CLibcurlCallback* pCallback, void* lpParam) { m_pCallbackParam = lpParam; m_pCallback = pCallback; } bool CLibcurl::DownloadToFile(LPCSTR lpUrl, LPCSTR lpFile) { CURLcode code = curl_easy_setopt(m_pCurl, CURLOPT_URL, lpUrl); DeleteFileA(lpFile); m_hFile = CreateFileA(lpFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == m_hFile) { return FALSE; } curl_easy_setopt(m_pCurl, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(m_pCurl, CURLOPT_PROGRESSFUNCTION, ProgressCallback); curl_easy_setopt(m_pCurl, CURLOPT_PROGRESSDATA, this); m_lfFlag = Lf_Download; //开始执行请求 m_curlCode = curl_easy_perform(m_pCurl); return CURLE_OK == m_curlCode; } bool CLibcurl::Post(LPCSTR lpUrl, LPCSTR lpData) { assert(lpData != NULL); curl_easy_setopt(m_pCurl, CURLOPT_POST, 1); curl_easy_setopt(m_pCurl, CURLOPT_POSTFIELDS, lpData); //curl_easy_setopt(m_pCurl, CURLOPT_POSTFIELDSIZE, lpData); curl_easy_setopt(m_pCurl, CURLOPT_URL, lpUrl); m_lfFlag = Lf_Post; m_strRespons.clear(); m_curlCode = curl_easy_perform(m_pCurl); return CURLE_OK == m_curlCode; } bool CLibcurl::Post(LPCSTR lpUrl, unsigned char* lpData, unsigned int nSize) { assert(lpData != NULL && nSize > 0); curl_easy_setopt(m_pCurl, CURLOPT_POST, 1); curl_easy_setopt(m_pCurl, CURLOPT_POSTFIELDS, lpData); curl_easy_setopt(m_pCurl, CURLOPT_POSTFIELDSIZE, nSize); curl_easy_setopt(m_pCurl, CURLOPT_URL, lpUrl); m_lfFlag = Lf_Post; m_strRespons.clear(); m_curlCode = curl_easy_perform(m_pCurl); return CURLE_OK == m_curlCode; } bool CLibcurl::Get(LPCSTR lpUrl) { assert(lpUrl != NULL); curl_easy_setopt(m_pCurl, CURLOPT_HTTPGET, 1); curl_easy_setopt(m_pCurl, CURLOPT_URL, lpUrl); curl_easy_setopt(m_pCurl, CURLOPT_FOLLOWLOCATION, 1);//支持重定向 curl_easy_setopt(m_pCurl, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(m_pCurl, CURLOPT_SSL_VERIFYHOST, 0L); m_lfFlag = Lf_Get; m_strRespons.clear(); m_curlCode = curl_easy_perform(m_pCurl); return CURLE_OK == m_curlCode; } const string& CLibcurl::GetRespons() const { return m_strRespons; } const char* CLibcurl::GetResponsPtr() const { return m_strRespons.c_str(); } size_t CLibcurl::WriteCallback(void* pBuffer, size_t nSize, size_t nMemByte, void* pParam) { //把下载到的数据以追加的方式写入文件(一定要有a,否则前面写入的内容就会被覆盖了) CLibcurl* pThis = (CLibcurl*)pParam; DWORD dwWritten = 0; switch (pThis->m_lfFlag) { case Lf_Download://下载 { if (pThis->m_hFile == INVALID_HANDLE_VALUE) return 0; if (!WriteFile(pThis->m_hFile, pBuffer, nSize*nMemByte, &dwWritten, NULL)) return 0; } break; case Lf_Post://Post数据 case Lf_Get://Get数据 { pThis->m_strRespons.append((const char*)pBuffer, nSize*nMemByte); dwWritten = nSize * nMemByte; } break; case Lf_None://未定义 break; } return dwWritten; } size_t CLibcurl::HeaderCallback(void* pBuffer, size_t nSize, size_t nMemByte, void* pParam) { CLibcurl* pThis = (CLibcurl*)pParam; return 0; } int CLibcurl::ProgressCallback(void *pParam, double dltotal, double dlnow, double ultotal, double ulnow) { CLibcurl* pThis = (CLibcurl*)pParam; if (pThis->m_pCallback) { pThis->m_pCallback->Progress(pThis->m_pCallbackParam, dltotal, dlnow); } return 0; } size_t CommonTools::receive_data(void *contents, size_t size, size_t nmemb, void *stream) { string *str = (string*)stream; (*str).append((char*)contents, size*nmemb); return size * nmemb; } size_t CommonTools::writedata2file(void *ptr, size_t size, size_t nmemb, FILE *stream) { size_t written = fwrite(ptr, size, nmemb, stream); return written; } int CommonTools::download_file(const char* url, const char outfilename[FILENAME_MAX]) { CURL *curl; FILE *fp; CURLcode res; /* 调用curl_global_init()初始化libcurl */ res = curl_global_init(CURL_GLOBAL_ALL); if (CURLE_OK != res) { printf("init libcurl failed."); curl_global_cleanup(); return -1; } /* 调用curl_easy_init()函数得到 easy interface型指针 */ curl = curl_easy_init(); if (curl) { fp = fopen(outfilename, "wb"); /* 调用curl_easy_setopt()设置传输选项 */ res = curl_easy_setopt(curl, CURLOPT_URL, url); if (res != CURLE_OK) { fclose(fp); curl_easy_cleanup(curl); return -1; } /* 根据curl_easy_setopt()设置的传输选项,实现回调函数以完成用户特定任务 */ res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CommonTools::writedata2file); if (res != CURLE_OK) { fclose(fp); curl_easy_cleanup(curl); return -1; } /* 根据curl_easy_setopt()设置的传输选项,实现回调函数以完成用户特定任务 */ res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); if (res != CURLE_OK) { fclose(fp); curl_easy_cleanup(curl); return -1; } res = curl_easy_perform(curl); // 调用curl_easy_perform()函数完成传输任务 fclose(fp); /* Check for errors */ if (res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); curl_easy_cleanup(curl); return -1; } /* always cleanup */ curl_easy_cleanup(curl); // 调用curl_easy_cleanup()释放内存 } curl_global_cleanup(); return 0; } CURLcode CommonTools::HttpGet(const std::string & strUrl, std::string & strResponse, int nTimeout) { CURLcode res; CURL* pCURL = curl_easy_init(); if (pCURL == NULL) { return CURLE_FAILED_INIT; } curl_easy_setopt(pCURL, CURLOPT_URL, strUrl.c_str()); //curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); curl_easy_setopt(pCURL, CURLOPT_NOSIGNAL, 1L); curl_easy_setopt(pCURL, CURLOPT_TIMEOUT, nTimeout); curl_easy_setopt(pCURL, CURLOPT_NOPROGRESS, 1L); curl_easy_setopt(pCURL, CURLOPT_WRITEFUNCTION, CommonTools::receive_data); curl_easy_setopt(pCURL, CURLOPT_WRITEDATA, (void*)&strResponse); res = curl_easy_perform(pCURL); curl_easy_cleanup(pCURL); return res; } CURLcode CommonTools::HttpPost(const std::string & strUrl, std::string szJson, std::string & strResponse, int nTimeout) { CURLcode res; char szJsonData[1024]; memset(szJsonData, 0, sizeof(szJsonData)); strcpy(szJsonData, szJson.c_str()); CURL* pCURL = curl_easy_init(); struct curl_slist* headers = NULL; if (pCURL == NULL) { return CURLE_FAILED_INIT; } CURLcode ret; ret = curl_easy_setopt(pCURL, CURLOPT_URL, strUrl.c_str()); // std::cout << ret << std::endl; ret = curl_easy_setopt(pCURL, CURLOPT_POST, 1L); headers = curl_slist_append(headers, "content-type:application/json"); ret = curl_easy_setopt(pCURL, CURLOPT_HTTPHEADER, headers); ret = curl_easy_setopt(pCURL, CURLOPT_POSTFIELDS, szJsonData); //curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); ret = curl_easy_setopt(pCURL, CURLOPT_TIMEOUT, nTimeout); ret = curl_easy_setopt(pCURL, CURLOPT_WRITEFUNCTION, CommonTools::receive_data); ret = curl_easy_setopt(pCURL, CURLOPT_WRITEDATA, (void*)&strResponse); res = curl_easy_perform(pCURL); curl_easy_cleanup(pCURL); return res; }