1. #include <string>
  2. #include <stdio.h>
  3. #include <iostream>
  4. #include<fstream>
  5.  
  6. #include "curl.h"
  7.  
  8. #ifdef WIN32
  9. #include <corecrt_io.h>
  10. #else
  11. #include "unistd.h"
  12. #include<unistd.h>
  13. #endif
  14. #include "curl_http.h"
  15. #include "md5.h"
  16. #include "OperateFile.h"
  17. using namespace std;
  18.  
  19. curl_http::curl_http()
  20. : list(NULL)
  21. {
  22. }
  23.  
  24. curl_http::~curl_http()
  25. {
  26. if (list)
  27. {
  28. curl_slist_free_all(list);
  29. }
  30. }
  31.  
  32. void curl_http::add_header(const std::string & header)
  33. {
  34. list = curl_slist_append(list, header.c_str());
  35. }
  36.  
  37. static size_t OnWriteData(void* buffer, size_t size, size_t nmemb, void* lpVoid)
  38. {
  39. std::string* str = dynamic_cast<std::string*>((std::string *)lpVoid);
  40. if (NULL == str || NULL == buffer)
  41. {
  42. return -1;
  43. }
  44. char* pData = (char*)buffer;
  45. str->append(pData, size * nmemb);
  46. return nmemb;
  47. }
  48.  
  49. int curl_http::Post(std::string strUrl, std::string strPost, int& statusCode, std::string& strResponse) {
  50. CURLcode res;
  51. CURL* curl = curl_easy_init();
  52. if (NULL == curl)
  53. {
  54. return CURLE_FAILED_INIT;
  55. }
  56. curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
  57. if (list)
  58. {
  59. curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
  60. }
  61. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); //验证SSL证书
  62. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); //验证主机名的SSL
  63. curl_easy_setopt(curl, CURLOPT_POST, 1); //发送一个HTTP POST要求
  64. curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPost.c_str()); //用这个数据发送一个POST
  65. curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL); //读取数据回调
  66. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData); //写入数据的回调
  67. curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse); //数据指针传递给写回调
  68. curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); //不安装信号处理程序
  69. curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3); //整个请求超时时间
  70. curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3); //连接阶段超时时间
  71. curl_easy_setopt(curl, CURLOPT_USERAGENT, "pc_student"); //用户代理:标头
  72. res = curl_easy_perform(curl);
  73. curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &statusCode);
  74. curl_easy_cleanup(curl);
  75. return res;
  76. }
  77.  
  78. static size_t OnWriteFile(void* buffer, size_t size, size_t nmemb, void* lpVoid)
  79. {
  80. FILE* stream = (FILE*)lpVoid;
  81. if (nullptr == stream || nullptr == buffer)
  82. {
  83. return -1;
  84. }
  85. size_t nWrite = fwrite(buffer, size, nmemb, stream);
  86. return nWrite;
  87. }
  88.  
  89. int OnProgress(void *ptr, double totalToDownload, double nowDownloaded, double totalToUpLoad, double nowUpLoaded)
  90. {
  91. int tmp = 0;
  92. long localLen = *(long*)ptr;
  93. if ( totalToDownload > 0 )
  94. {
  95. tmp = (int)((nowDownloaded + (double)localLen) / (totalToDownload + (double)localLen) * 100);
  96. }
  97. printf("下载进度%0d%%\r", tmp);
  98. return 0;
  99. }
  100.  
  101. size_t ProgressFunc(double* pFileLen,
  102. double t,// 下载时总大小
  103. double d, // 已经下载大小
  104. double ultotal, // 上传是总大小
  105. double ulnow) // 已经上传大小
  106. {
  107. if(t == 0) return 0;
  108. *pFileLen = d;
  109. return 0;
  110. }
  111.  
  112. curl_http_downloader::curl_http_downloader(const std::string& name)
  113. : m_file(nullptr)
  114. , m_TargetName(name)
  115. , m_progress(nullptr)
  116. {
  117. }
  118.  
  119. curl_http_downloader::~curl_http_downloader()
  120. {
  121. }
  122.  
  123. bool curl_http_downloader::DownloadFileContent(const std::string& url,
  124. const std::string& Targetfilepath,
  125. const std::string& Temfilepath,
  126. string SizeRange)
  127. {
  128. CURLcode res;
  129. if(OpenFile(Temfilepath,m_file) || OpenFile(Targetfilepath,m_ExitFile))
  130. return false;
  131.  
  132. CURL* _curl = curl_easy_init();
  133.  
  134. if (nullptr == _curl)
  135. {
  136. CloseFile(m_file);
  137. CloseFile(m_ExitFile);
  138. return false;
  139. }
  140.  
  141. curl_easy_setopt(_curl, CURLOPT_URL, url.c_str());
  142. curl_easy_setopt(_curl, CURLOPT_WRITEFUNCTION, OnWriteFile);
  143. curl_easy_setopt(_curl, CURLOPT_WRITEDATA, m_file);
  144. curl_easy_setopt(_curl, CURLOPT_NOPROGRESS, false);
  145. curl_easy_setopt(_curl, CURLOPT_PROGRESSFUNCTION, OnProgress);
  146. curl_easy_setopt(_curl, CURLOPT_NOSIGNAL, 1L);
  147. curl_easy_setopt(_curl, CURLOPT_LOW_SPEED_LIMIT, 1L);
  148. curl_easy_setopt(_curl, CURLOPT_LOW_SPEED_TIME, 5L);
  149.  
  150. curl_easy_setopt(_curl, CURLOPT_HEADER, 0L);
  151. curl_easy_setopt(_curl, CURLOPT_NOBODY, 0L);
  152. curl_easy_setopt(_curl, CURLOPT_FOLLOWLOCATION, 1L);
  153. //curl_easy_setopt(_curl, CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t)1000);
  154.  
  155. if (SizeRange == "")
  156. curl_easy_setopt(_curl, CURLOPT_RESUME_FROM, m_LocalFilelen);
  157. else
  158. curl_easy_setopt(_curl, CURLOPT_RANGE, SizeRange.c_str());
  159.  
  160. curl_easy_setopt(_curl, CURLOPT_PROGRESSDATA, &m_LocalFilelen);
  161.  
  162. res = curl_easy_perform(_curl); //完成curl_easy_setopt指定的所有选项,并返回状态
  163. curl_easy_cleanup(_curl);
  164.  
  165. CloseFile(m_file);
  166. CloseFile(m_ExitFile);
  167.  
  168. if (CURLE_OK == res)
  169. return true;
  170. else
  171. return false;
  172. }
  173.  
  174. int curl_http_downloader::Download(const std::string& url, const std::string& path, progressFunc func,string CurrectMD5)
  175. {
  176. m_filePath = path;
  177.  
  178. #ifdef WIN32
  179. m_TargetFileNamepath = m_filePath + "temp.downloading";
  180. m_Tempinterfilepath = m_filePath + "temp";
  181. #else
  182. m_TargetFileNamepath = m_filePath + "temp.downloading";
  183. m_Tempinterfilepath = m_filePath + "temp";
  184. #endif
  185.  
  186. m_LocalFilelen = GetFileLength(m_TargetFileNamepath); //获取已下载文件大小
  187. bool CricleFlags = true; //CricleFlags为dfalse时,说明下载文件错误,重新下载错误部分
  188. bool Downloadflags = true; //Downloadflags为dfalse时,将进行下载与拼接
  189. string range = "";
  190. do{
  191.  
  192. bool result = DownloadFileContent(url, m_TargetFileNamepath, m_Tempinterfilepath, range);
  193. if (result) {
  194. std::string fullName = m_filePath + m_TargetName;
  195.  
  196. if(Downloadflags)
  197. MergerFile(m_Tempinterfilepath,m_TargetFileNamepath);
  198. else
  199. ToRightMergerFile(m_TargetFileNamepath, m_Tempinterfilepath);
  200.  
  201. string m_fileMD5 = MD5::getFileMd5(m_TargetFileNamepath);
  202.  
  203. int bmoved = 0;
  204. #ifdef WIN32
  205. if (_access(m_TargetFileNamepath.c_str(), 0) == 0)
  206. remove(fullName.c_str());
  207. #else
  208. if (access(m_TargetFileNamepath.c_str(), 0) == 0)
  209. remove(fullName.c_str());
  210. #endif // WIN 32
  211.  
  212. if(CurrectMD5 == m_fileMD5){ //MD5校验
  213. bmoved = rename(m_TargetFileNamepath.c_str(), fullName.c_str());
  214. remove(m_Tempinterfilepath.c_str());
  215. CricleFlags = true;
  216. }
  217. else{
  218. ExchangFileName(m_Tempinterfilepath, m_TargetFileNamepath);
  219. remove(m_Tempinterfilepath.c_str());
  220. if((Downloadflags = !Downloadflags))
  221. range = "";
  222. else
  223. range = "0-" + to_string(m_LocalFilelen-1) ;
  224. CricleFlags = false;
  225. }
  226. if (bmoved) {
  227. //std::cerr << "move file: " << m_fileNameTmp << " to: " << fullName <<" failed! ";
  228. return -1;
  229. }
  230. }
  231. else{
  232. if(GetFileLength(m_Tempinterfilepath)){
  233. MergerFile(m_Tempinterfilepath,m_TargetFileNamepath);
  234. remove(m_Tempinterfilepath.c_str());
  235. }
  236. }
  237. }while(!CricleFlags);
  238. CloseFile(m_file);
  239. CloseFile(m_ExitFile);
  240. return 0;
  241. }
  242.  
  243. int curl_http_downloader::Pause() {
  244. if (nullptr != m_download_info) {
  245. m_download_info->status = PAUSED;
  246. }
  247. return 0;
  248. }

CURL 实战下载的更多相关文章

  1. curl -O 下载文件

    curl -O 下载文件 学习了:http://blog.csdn.net/wulong710/article/details/53127606 curl -O http://a.b.c/a.tar ...

  2. Linux如何使用cURL分割下载大文件

    Linux如何使用cURL分割下载大文件 - 51CTO.COM http://os.51cto.com/art/201508/489368.htm

  3. curl多线程下载类

    <?php /** * curl多线程下载类 */class MultiHttpRequest{ public $urls = array (); private $res = array () ...

  4. Python简单网络爬虫实战—下载论文名称,作者信息(下)

    在Python简单网络爬虫实战—下载论文名称,作者信息(上)中,学会了get到网页内容以及在谷歌浏览器找到了需要提取的内容的数据结构,接下来记录我是如何找到所有author和title的 1.从sou ...

  5. Windows系统下curl的下载和配置

    curl的下载和配置 简介:用URL规则在命令行下工作的文件传输工具. 下载:下载地址为 https://curl.haxx.se/download.html,在最底部找到Windows的版本,我下载 ...

  6. C++代码利用pthread线程池与curl批量下载地图瓦片数据

    项目需求编写的程序,稳定性有待进一步测试. 适用场景:在网络地图上,比如天地图与谷歌地图,用户用鼠标在地图上拉一个矩形框,希望下载该矩形框内某一层级的瓦片数据,并将所有瓦片拼接成一个完整的,包含地理坐 ...

  7. curl定时任务下载执行

    服务器入侵后有定时任务执行如下,通过cron,下载脚本并执行!达到杀不死的木马进程 */5 * * * * curl -fsSL http://xxxx/pm.sh?0111 | sh curl参数解 ...

  8. Linux curl 命令下载文件

    引用自http://blog.csdn.net/wh211212/article/details/54285921 命令:curl 在Linux中curl是一个利用URL规则在命令行下工作的文件传输工 ...

  9. wget和curl方式下载JDK

    有时候我们需要在Linux服务器上安装Oracle JDK,这时候我们发现直接复制网页上面的地址是不能下载的 以下载jdk-8u101-linux-i586.tar.gz为例,右键查看到的地址为htt ...

随机推荐

  1. object_pool对象池

    object_pool对象池 object_pool是用于类实例(对象)的内存池,它能够在析构时调用所有已经分配的内存块调用析构函数,从而正确释放资源,需要包含以下头文件: #include < ...

  2. 如何屏蔽 iOS 软件自动更新,去除更新通知和标记

    适用于 iOS.iPadOS 和 watchOS,即 iPhone.iPad 和 Apple Watch 通用. 请访问原文链接:https://sysin.org/article/Disable-i ...

  3. 你是不是对MD5算法有误解?

    大家常听到"MD5加密"."对称加密"."非对称加密",那么MD5属于哪种加密算法? 面试问这样的问题,准是在给你挖坑. "MD5 ...

  4. 第三方跨平台进程和系统监控库gopsutil

    gopsutil psutil是一个跨平台进程和系统监控的Python库,而gopsutil是其Go语言版本的实现.本文介绍了它的基本使用. Go语言部署简单.性能好的特点非常适合做一些诸如采集系统信 ...

  5. Step By Step(Lua系统库)

    Step By Step(Lua系统库) Lua为了保证高度的可移植性,因此,它的标准库仅仅提供了非常少的功能,特别是和OS相关的库.但是Lua还提供了一些扩展库,比如Posix库等.对于文件操作而言 ...

  6. conda 按照指定源下载python包

    conda 按照指定源下载python包 换成了国内的pip源就可以正常安装了,我使用的是:pip install xlrd -i http://pypi.douban.com/simple --tr ...

  7. 自动驾驶QNX,Linux,Autosar概述

    自动驾驶QNX,Linux,Autosar概述 QNX是一个分布式.嵌入式.可规模扩展的实时操作系统.遵循POSIX.1 (程序接口)和POSIX.2 (Shell和工具).部分遵循POSIX.1b( ...

  8. TVM量化小结手册

    TVM量化小结手册 文章目录 Offical References TVM quantization roadmap INT8 quantization proposal Quantization S ...

  9. Bayer滤镜转换颜色方案

    Bayer滤镜如何转换颜色? Bayer模式是颜色模式,被广泛应用于CCD和CMOS摄像头.相机使用了拜耳滤镜,分别过滤得到红绿蓝三种颜色.既然要得到的是红绿蓝频段光线的强度,要通过的就是红绿蓝光,就 ...

  10. OpenGL在图形管道中调用了什么用户模式图形驱动程序(UMD)?

    OpenGL在图形管道中调用了什么用户模式图形驱动程序(UMD)? 图形硬件供应商,需要为显示适配器编,编写用户模式显示驱动程序.用户模式显示驱动程序,是由Microsoft Direct3D运行时加 ...