CurlClient.cpp 26 KB

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