CurlClient.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. #include "stdafx.h"
  2. #include "CurlClient.h"
  3. #include "CharEncoding.h"
  4. #include <sys/stat.h>
  5. CCurlClient::CCurlClient(void)
  6. {
  7. m_bDebug = FALSE;
  8. m_headers = NULL;
  9. }
  10. CCurlClient::~CCurlClient(void)
  11. {
  12. // 释放curl的全局对象;
  13. curl_global_cleanup();
  14. }
  15. INT CCurlClient::Initialize()
  16. {
  17. // 初始化全局调用模式;
  18. CURLcode res = ::curl_global_init( CURL_GLOBAL_ALL );
  19. if( CURLE_OK != res )
  20. {
  21. fprintf( stderr, "curl_global_init failed: %d \n", res );
  22. return -1;
  23. }
  24. return 0;
  25. }
  26. static int OnDebug(CURL *, curl_infotype itype, char * pData, size_t size, void *)
  27. {
  28. if(itype == CURLINFO_TEXT)
  29. {
  30. //TRACE("[TEXT]%s\n", pData);
  31. //LOG4C((LOG_WARN, "[TEXT]%s\n", pData));
  32. }
  33. else if(itype == CURLINFO_HEADER_IN)
  34. {
  35. //TRACE("[HEADER_IN]%s\n", pData);
  36. //LOG4C((LOG_WARN, "[HEADER_IN]%s\n", pData));
  37. }
  38. else if(itype == CURLINFO_HEADER_OUT)
  39. {
  40. //TRACE("[HEADER_OUT]%s\n", pData);
  41. //LOG4C((LOG_WARN, "[HEADER_OUT]%s\n", pData));
  42. }
  43. else if(itype == CURLINFO_DATA_IN)
  44. {
  45. //TRACE("[DATA_IN]%s\n", pData);
  46. //LOG4C((LOG_WARN, "[DATA_IN]%s\n", pData));
  47. }
  48. else if(itype == CURLINFO_DATA_OUT)
  49. {
  50. //TRACE("[DATA_OUT]%s\n", pData);
  51. //LOG4C((LOG_WARN, "[DATA_OUT]%s\n", pData));
  52. }
  53. return 0;
  54. }
  55. size_t CCurlClient::OnWriteData(const void *ptr, size_t size, size_t nmemb, std::string *stream)
  56. {
  57. if( NULL == stream || NULL == ptr )
  58. return -1;
  59. stream->append((char*)ptr, size * nmemb);
  60. return nmemb;
  61. }
  62. int CCurlClient::Post(const std::string & strUrl, const std::string & strPost, std::string & strResponse, long time_out /*= 3*/)
  63. {
  64. CURLcode res;
  65. CURL* curl = curl_easy_init();
  66. if(NULL == curl)
  67. {
  68. return CURLE_FAILED_INIT;
  69. }
  70. if(m_bDebug)
  71. {// 是否开启调试日志输出;
  72. curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
  73. curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
  74. }
  75. // 设置URL地址;
  76. curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
  77. // 设置POST方式;
  78. curl_easy_setopt(curl, CURLOPT_POST, 1);
  79. // 设置POST参数;
  80. curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPost.c_str());
  81. // 设置回调函数-读取;
  82. curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
  83. // 设置回调函数-写入;
  84. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
  85. // 设置回调函数-写入的缓存区;
  86. curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
  87. // 设置(多线程下,只是尽量减少)无签名;
  88. curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
  89. // 设置连接超时值(单位毫秒);
  90. curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30000);
  91. // 设置操作超时值(单位毫秒);
  92. curl_easy_setopt(curl, CURLOPT_TIMEOUT, time_out);
  93. // 设置头;
  94. curl_easy_setopt(curl, CURLOPT_HTTPHEADER, m_headers);
  95. // 执行POST提交;
  96. res = curl_easy_perform(curl);
  97. // 释放资源;
  98. curl_easy_cleanup(curl);
  99. //curl_global_cleanup();
  100. ClearHeaders(); /* free the header list */
  101. return res;
  102. }
  103. int CCurlClient::Post(IN LPCTSTR lpUrl, IN LPCTSTR lpPost, OUT LPTSTR lpResponse, IN CONST INT& nMaxlen, long time_out /*= 3*/)
  104. {
  105. if ( lpUrl == NULL || lpPost == NULL )
  106. return CURLE_FAILED_INIT;
  107. string strUrl;
  108. string strPost;
  109. string strResponse;
  110. #ifdef UNICODE
  111. CharEncoding::UNICODE2ASCII((LPWCH)lpUrl, strUrl);
  112. CharEncoding::UNICODE2ASCII((LPWCH)lpPost, strPost);
  113. int res = Post(strUrl, strPost, strResponse) ;
  114. if ( CURLE_OK == res )
  115. {
  116. CharEncoding::ASCII2UNICODE(strResponse.c_str(), (LPWCH)lpResponse, nMaxlen);
  117. return CURLE_OK;
  118. }
  119. return res;
  120. #else
  121. strUrl = lpUrl;
  122. strPost = lpPost;
  123. int res = Post(strUrl, strPost, strResponse, time_out) ;
  124. if ( CURLE_OK == res )
  125. {
  126. sprintf_s(lpResponse, nMaxlen, "%s", strResponse.c_str());
  127. return CURLE_OK;
  128. }
  129. return res;
  130. #endif
  131. }
  132. int CCurlClient::Post(IN CString& strUrl, IN CString& strPost, OUT CString& strResponse, long time_out /*= 3*/)
  133. {
  134. if ( strUrl.IsEmpty() || strPost.IsEmpty() )
  135. return CURLE_FAILED_INIT;
  136. string url;
  137. string post;
  138. string response;
  139. #ifdef UNICODE
  140. CharEncoding::UNICODE2ASCII((LPWCH)strUrl.GetString(), url);
  141. CharEncoding::UNICODE2ASCII((LPWCH)strPost.GetString(), post);
  142. int res = Post(url, post, response) ;
  143. if ( CURLE_OK == res )
  144. {
  145. WCHAR* pResult = CharEncoding::ASCII2UNICODE(response.c_str());
  146. if ( pResult )
  147. {
  148. strResponse = pResult;
  149. delete []pResult;
  150. pResult = NULL;
  151. return CURLE_OK;
  152. }
  153. }
  154. return res;
  155. #else
  156. url = strUrl.GetString();
  157. post = strPost.GetString();
  158. int res = Post(url, post, response, time_out) ;
  159. if ( CURLE_OK == res )
  160. {
  161. strResponse = response.c_str();
  162. return CURLE_OK;
  163. }
  164. return res;
  165. #endif
  166. }
  167. int CCurlClient::Get(const std::string & strUrl, std::string & strResponse, long time_out /*= 3*/)
  168. {
  169. CURLcode res;
  170. CURL* curl = curl_easy_init();
  171. if(NULL == curl)
  172. {
  173. return CURLE_FAILED_INIT;
  174. }
  175. if(m_bDebug)
  176. {
  177. curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
  178. curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
  179. }
  180. // 设置URL地址;
  181. curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
  182. // 设置回调函数-读取;
  183. curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
  184. // 设置回调函数-写入;
  185. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
  186. // 设置回调函数-写入的缓存区;
  187. curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
  188. /**
  189. * 当多个线程都使用超时处理的时候,同时主线程中有sleep或是wait等操作。
  190. * 如果不设置这个选项,libcurl将会发信号打断这个wait从而导致程序退出。
  191. */
  192. // 设置(多线程下,只是尽量减少)无签名;
  193. curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
  194. // 设置连接超时值;
  195. curl_easy_setopt(curl,CURLOPT_CONNECTTIMEOUT,5000);
  196. // 设置超时值;
  197. curl_easy_setopt(curl,CURLOPT_TIMEOUT, time_out);
  198. // 设置头;
  199. curl_easy_setopt(curl, CURLOPT_HTTPHEADER, m_headers);
  200. res = curl_easy_perform(curl);
  201. curl_easy_cleanup(curl);
  202. //curl_global_cleanup();
  203. ClearHeaders(); /* free the header list */
  204. return res;
  205. }
  206. int CCurlClient::Get(IN LPCTSTR lpUrl, OUT LPTSTR lpResponse, IN CONST INT& nMaxlen, long time_out /*= 3*/)
  207. {
  208. if ( lpUrl == NULL )
  209. return CURLE_FAILED_INIT;
  210. string strUrl;
  211. string strResponse;
  212. #ifdef UNICODE
  213. CharEncoding::UNICODE2ASCII((LPWCH)lpUrl, strUrl);
  214. int res = Get(strUrl, strResponse) ;
  215. if ( CURLE_OK == res )
  216. {
  217. CharEncoding::ASCII2UNICODE(strResponse.c_str(), (LPWCH)lpResponse, nMaxlen);
  218. return CURLE_OK;
  219. }
  220. return res;
  221. #else
  222. strUrl = lpUrl;
  223. int res = Get(strUrl, strResponse, time_out) ;
  224. if ( CURLE_OK == res )
  225. {
  226. sprintf_s(lpResponse, nMaxlen, "%s", strResponse.c_str());
  227. return CURLE_OK;
  228. }
  229. return res;
  230. #endif
  231. }
  232. int CCurlClient::Get(IN CString& strUrl, OUT CString& strResponse, long time_out /*= 3*/)
  233. {
  234. if ( strUrl.IsEmpty() )
  235. return CURLE_FAILED_INIT;
  236. string url;
  237. string post;
  238. string response;
  239. #ifdef UNICODE
  240. CharEncoding::UNICODE2ASCII((LPWCH)strUrl.GetString(), url);
  241. int res = Get(url, response) ;
  242. if ( CURLE_OK == res )
  243. {
  244. WCHAR* pResult = CharEncoding::ASCII2UNICODE(response.c_str());
  245. if ( pResult )
  246. {
  247. strResponse = pResult;
  248. delete []pResult;
  249. pResult = NULL;
  250. return CURLE_OK;
  251. }
  252. }
  253. return res;
  254. #else
  255. url = strUrl.GetString();
  256. int res = Get(url, response, time_out) ;
  257. if ( CURLE_OK == res )
  258. {
  259. strResponse = response.c_str();
  260. return CURLE_OK;
  261. }
  262. return res;
  263. #endif
  264. }
  265. CURLcode CCurlClient::Posts(const std::string & strUrl, const std::string & strPost, std::string & strResponse, const char * pCaPath, long time_out /*= 3*/)
  266. {
  267. CURLcode res;
  268. CURL* curl = curl_easy_init();
  269. if(NULL == curl)
  270. {
  271. return CURLE_FAILED_INIT;
  272. }
  273. if(m_bDebug)
  274. {
  275. curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
  276. curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
  277. }
  278. // 设置URL地址;
  279. curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
  280. // 设置POST提交方式;
  281. curl_easy_setopt(curl, CURLOPT_POST, 1);
  282. // 设置POST参数;
  283. curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPost.c_str());
  284. // 设置回调函数-读取;
  285. curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
  286. // 设置回调函数-写入;
  287. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
  288. // 设置回调函数-写入的缓存区;
  289. curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
  290. // 设置;
  291. curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
  292. if(NULL == pCaPath || pCaPath[0] == '\0')
  293. {
  294. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
  295. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
  296. }
  297. else
  298. {
  299. //缺省情况就是PEM,所以无需设置,另外支持DER
  300. //curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,"PEM");
  301. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);
  302. curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);
  303. }
  304. // 设置连接超时值;
  305. curl_easy_setopt(curl,CURLOPT_CONNECTTIMEOUT,5000);
  306. // 设置超时值;
  307. curl_easy_setopt(curl,CURLOPT_TIMEOUT, time_out);
  308. // 设置头;
  309. curl_easy_setopt(curl, CURLOPT_HTTPHEADER, m_headers);
  310. // 执行POST提交;
  311. res = curl_easy_perform(curl);
  312. // 释放资源;
  313. curl_easy_cleanup(curl);
  314. //curl_global_cleanup();
  315. ClearHeaders(); /* free the header list */
  316. return res;
  317. }
  318. int CCurlClient::Posts(IN LPCTSTR lpUrl, IN LPCTSTR lpPost, OUT LPTSTR lpResponse, IN CONST INT& nMaxlen, IN LPCTSTR lpCaPath /* = NULL */, long time_out /*= 3*/)
  319. {
  320. if ( lpUrl == NULL || lpPost == NULL )
  321. return CURLE_FAILED_INIT;
  322. string strUrl;
  323. string strPost;
  324. string strCapath;
  325. string strResponse;
  326. #ifdef UNICODE
  327. CharEncoding::UNICODE2ASCII((LPWCH)lpUrl, strUrl);
  328. CharEncoding::UNICODE2ASCII((LPWCH)lpPost, strPost);
  329. CharEncoding::UNICODE2ASCII((LPWCH)lpCaPath, strCapath);
  330. int res = Posts(strUrl, strPost, strResponse, strCapath.c_str()) ;
  331. if ( CURLE_OK == res )
  332. {
  333. CharEncoding::ASCII2UNICODE(strResponse.c_str(), (LPWCH)lpResponse, nMaxlen);
  334. return CURLE_OK;
  335. }
  336. return res;
  337. #else
  338. strUrl = lpUrl;
  339. strPost = lpPost;
  340. strCapath = lpCaPath;
  341. int res = Posts(strUrl, strPost, strResponse, strCapath.c_str(), time_out ) ;
  342. if ( CURLE_OK == res )
  343. {
  344. sprintf_s(lpResponse, nMaxlen, "%s", strResponse.c_str());
  345. return CURLE_OK;
  346. }
  347. return res;
  348. #endif
  349. }
  350. int CCurlClient::Posts(IN CString& strUrl, IN CString& strPost, OUT CString& strResponse, IN const CString& strCaPath /* = _T("") */, long time_out /*= 3*/)
  351. {
  352. if ( strUrl.IsEmpty() || strPost.IsEmpty() )
  353. return CURLE_FAILED_INIT;
  354. string url;
  355. string post;
  356. string capth;
  357. string response;
  358. #ifdef UNICODE
  359. CharEncoding::UNICODE2ASCII((LPWCH)strUrl.GetString(), url);
  360. CharEncoding::UNICODE2ASCII((LPWCH)strPost.GetString(), post);
  361. CharEncoding::UNICODE2ASCII((LPWCH)strCaPath.GetString(), capth);
  362. int res = Posts(url, post, response, capth.c_str()) ;
  363. if ( CURLE_OK == res )
  364. {
  365. WCHAR* pResult = CharEncoding::ASCII2UNICODE(response.c_str());
  366. if ( pResult )
  367. {
  368. strResponse = pResult;
  369. delete []pResult;
  370. pResult = NULL;
  371. return CURLE_OK;
  372. }
  373. }
  374. return res;
  375. #else
  376. url = strUrl.GetString();
  377. post = strPost.GetString();
  378. capth = strCaPath.GetString();
  379. int res = Posts(url, post, response, capth.c_str(), time_out) ;
  380. if ( CURLE_OK == res )
  381. {
  382. strResponse = response.c_str();
  383. return CURLE_OK;
  384. }
  385. return res;
  386. #endif
  387. }
  388. int CCurlClient::Gets(const std::string & strUrl, std::string & strResponse, const char * pCaPath, long time_out /*= 3*/)
  389. {
  390. CURLcode res;
  391. CURL* curl = curl_easy_init();
  392. if(NULL == curl)
  393. {
  394. return CURLE_FAILED_INIT;
  395. }
  396. if(m_bDebug)
  397. {
  398. curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
  399. curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
  400. }
  401. curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
  402. curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
  403. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
  404. curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
  405. curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
  406. if(NULL == pCaPath || pCaPath[0] == '\0')
  407. {
  408. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
  409. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
  410. }
  411. else
  412. {
  413. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);
  414. curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);
  415. }
  416. curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5000);
  417. curl_easy_setopt(curl, CURLOPT_TIMEOUT, time_out);
  418. // 设置头;
  419. curl_easy_setopt(curl, CURLOPT_HTTPHEADER, m_headers);
  420. res = curl_easy_perform(curl);
  421. curl_easy_cleanup(curl);
  422. //curl_global_cleanup();
  423. ClearHeaders(); /* free the header list */
  424. return res;
  425. }
  426. int CCurlClient::Gets(IN LPCTSTR lpUrl, OUT LPTSTR lpResponse, IN CONST INT& nMaxlen, IN LPCTSTR lpCaPath /* = NULL */, long time_out /*= 3*/)
  427. {
  428. if ( lpUrl == NULL )
  429. return CURLE_FAILED_INIT;
  430. string strUrl;
  431. string strCapath;
  432. string strResponse;
  433. #ifdef UNICODE
  434. CharEncoding::UNICODE2ASCII((LPWCH)lpUrl, strUrl);
  435. CharEncoding::UNICODE2ASCII((LPWCH)lpCaPath, strCapath);
  436. int res = Gets(strUrl, strResponse, strCapath.c_str()) ;
  437. if ( CURLE_OK == res )
  438. {
  439. CharEncoding::ASCII2UNICODE(strResponse.c_str(), (LPWCH)lpResponse, nMaxlen);
  440. return CURLE_OK;
  441. }
  442. return res;
  443. #else
  444. strUrl = lpUrl;
  445. strCapath = lpCaPath;
  446. int res = Gets(strUrl, strResponse, strCapath.c_str(), time_out) ;
  447. if ( CURLE_OK == res )
  448. {
  449. sprintf_s(lpResponse, nMaxlen, "%s", strResponse.c_str());
  450. return CURLE_OK;
  451. }
  452. return res;
  453. #endif
  454. }
  455. int CCurlClient::Gets(IN CString& strUrl, OUT CString& strResponse, IN const CString& strCaPath /* = _T("") */, long time_out /*= 3*/)
  456. {
  457. if ( strUrl.IsEmpty() )
  458. return CURLE_FAILED_INIT;
  459. string url;
  460. string post;
  461. string capth;
  462. string response;
  463. #ifdef UNICODE
  464. CharEncoding::UNICODE2ASCII((LPWCH)strUrl.GetString(), url);
  465. CharEncoding::UNICODE2ASCII((LPWCH)strCaPath.GetString(), capth);
  466. int res = Gets(url, response, capth.c_str()) ;
  467. if ( CURLE_OK == res )
  468. {
  469. WCHAR* pResult = CharEncoding::ASCII2UNICODE(response.c_str());
  470. if ( pResult )
  471. {
  472. strResponse = pResult;
  473. delete []pResult;
  474. pResult = NULL;
  475. return CURLE_OK;
  476. }
  477. }
  478. return res;
  479. #else
  480. url = strUrl.GetString();
  481. capth = strCaPath.GetString();
  482. int res = Gets(url, response, capth.c_str(), time_out) ;
  483. if ( CURLE_OK == res )
  484. {
  485. strResponse = response.c_str();
  486. return CURLE_OK;
  487. }
  488. return res;
  489. #endif
  490. }
  491. void CCurlClient::SetDebug(bool bDebug)
  492. {
  493. m_bDebug = bDebug;
  494. }
  495. void CCurlClient::SetHeaders(const std::string headers)
  496. {
  497. m_headers = curl_slist_append(m_headers, headers.c_str());
  498. }
  499. // 参考:https://blog.csdn.net/lengyuezuixue/article/details/81987695
  500. bool CCurlClient::DownloadEx(const std::string& url, const std::string& path, long time_out /* = 3000 */)
  501. {
  502. FILE* pf = NULL;
  503. curl_off_t local_file_len = -1;
  504. long file_size = 0;
  505. CURLcode res = CURLE_GOT_NOTHING;
  506. int c = 0;
  507. struct stat file_info;
  508. int use_resume = 0;
  509. // 获取本地文件大小;
  510. if (stat(path.c_str(), &file_info) == 0)
  511. {
  512. local_file_len = file_info.st_size;
  513. use_resume = 1;
  514. }
  515. // 采用追加方式打开文件,便于实现断点续传;
  516. int nErr = _tfopen_s(&pf, path.c_str(), "ab+");
  517. if (pf)
  518. {
  519. CURL* curl = curl_easy_init();
  520. if (NULL == curl)
  521. {
  522. //return CURLE_FAILED_INIT;
  523. return false;
  524. }
  525. curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
  526. curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, time_out);
  527. // 设置http头部处理函数;
  528. curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, OnGetContentLength);
  529. curl_easy_setopt(curl, CURLOPT_HEADERDATA, &file_size);
  530. if (url.find("https://") != std::string::npos)
  531. {
  532. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
  533. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
  534. }
  535. // 设置文件续传的位置给curl;
  536. curl_easy_setopt(curl, CURLOPT_RESUME_FROM_LARGE, use_resume ? local_file_len : 0);
  537. curl_easy_setopt(curl, CURLOPT_WRITEDATA, pf);
  538. //curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);//设置重定位URL,使用自动跳转,返回的头部中有Location(一般直接请求的url没找到),则继续请求Location对应的数据
  539. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteFile);
  540. curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L);
  541. curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
  542. res = curl_easy_perform(curl);
  543. fclose(pf);
  544. curl_easy_cleanup(curl);
  545. if (res == CURLE_OK)
  546. return true;
  547. }
  548. return false;
  549. }
  550. size_t CCurlClient::OnGetContentLength(void* ptr, size_t size, size_t nmemb, void* stream)
  551. {
  552. int r;
  553. long len = 0;
  554. /* _snscanf() is Win32 specific */
  555. // r = _snscanf(ptr, size * nmemb, "Content-Length: %ld\n", &len);
  556. r = sscanf_s((char*)ptr, "Content-Length: %ld\n", &len);
  557. if (r) /* Microsoft: we don't read the specs */
  558. *((long*)stream) = len;
  559. return size * nmemb;
  560. }
  561. size_t CCurlClient::OnWriteFile(const void* ptr, size_t size, size_t nmemb, void* stream)
  562. {
  563. if (NULL == stream || NULL == ptr)
  564. return -1;
  565. return fwrite(ptr, size, nmemb, (FILE*)stream);
  566. }
  567. int CCurlClient::FormPosts(std::string url, std::multimap<std::string, std::string> form_data, std::string& result, long time_out)
  568. {
  569. CURLcode res;
  570. CURL* curl = curl_easy_init();
  571. if (NULL == curl)
  572. {
  573. return CURLE_FAILED_INIT;
  574. }
  575. if (m_bDebug)
  576. {
  577. curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
  578. curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
  579. }
  580. // 表单参数;
  581. std::string post;
  582. CURLFORMcode rmcode;
  583. struct curl_httppost* formpost = NULL;
  584. struct curl_httppost* lastptr = NULL;
  585. std::multimap<std::string, std::string>::iterator it = form_data.begin();
  586. #if 0
  587. for (; it != form_data.end(); )
  588. {
  589. post.append(it->first);
  590. post.append("=");
  591. post.append(it->second);
  592. if (++it != form_data.end())
  593. post.append("&");
  594. else
  595. break;
  596. }
  597. // 设置POST参数;
  598. curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post.c_str());
  599. // 设置POST提交方式;
  600. res = curl_easy_setopt(curl, CURLOPT_POST, 1);
  601. #else
  602. for (; it != form_data.end(); it++)
  603. {
  604. rmcode = curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, it->first.c_str(), CURLFORM_COPYCONTENTS, it->second.c_str(), CURLFORM_END);
  605. }
  606. // 设置表单参数
  607. res = curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
  608. // 设置表头,表头内容可能不同
  609. //m_headers = curl_slist_append(m_headers, "Content-Type:multipart/form-data");
  610. //m_headers = curl_slist_append(m_headers, "Expect:");
  611. //m_headers = curl_slist_append(m_headers, "Accept-Encoding:gzip, deflate");//Accept-Encodeing冒号后面加东西就上传失败;
  612. //curl_easy_setopt(curl, CURLOPT_HTTPHEADER, m_headers);
  613. #endif
  614. // 设置URL地址;
  615. res = curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
  616. // 设置回调函数-读取;
  617. res = curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
  618. // 设置回调函数-写入;
  619. res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
  620. // 设置回调函数-写入的缓存区;
  621. res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&result);
  622. // 设置;
  623. res = curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
  624. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
  625. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
  626. curl_easy_setopt(curl, CURLOPT_AUTOREFERER, 1); // 以下3个为重定向设置
  627. curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); //返回的头部中有Location(一般直接请求的url没找到),则继续请求Location对应的数据
  628. curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 1);//查找次数,防止查找太深
  629. curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30);//连接超时,这个数值如果设置太短可能导致数据请求不到就断开了
  630. // 设置超时值;
  631. res = curl_easy_setopt(curl, CURLOPT_TIMEOUT, time_out);
  632. // 设置头;
  633. res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, m_headers);
  634. // 执行POST提交;
  635. res = curl_easy_perform(curl);
  636. // 释放资源;
  637. curl_easy_cleanup(curl);
  638. //curl_global_cleanup();
  639. ClearHeaders(); /* free the header list */
  640. // 释放表单
  641. curl_formfree(formpost);
  642. return res;
  643. }