CurlClient.cpp 26 KB

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