#include <string>
#include <stdio.h>
#include <iostream>
#include<fstream> #include "curl.h" #ifdef WIN32
#include <corecrt_io.h>
#else
#include "unistd.h"
#include<unistd.h>
#endif
#include "curl_http.h"
#include "md5.h"
#include "OperateFile.h"
using namespace std; curl_http::curl_http()
: list(NULL)
{
} curl_http::~curl_http()
{
if (list)
{
curl_slist_free_all(list);
}
} void curl_http::add_header(const std::string & header)
{
list = curl_slist_append(list, header.c_str());
} static size_t OnWriteData(void* buffer, size_t size, size_t nmemb, void* lpVoid)
{
std::string* str = dynamic_cast<std::string*>((std::string *)lpVoid);
if (NULL == str || NULL == buffer)
{
return -1;
}
char* pData = (char*)buffer;
str->append(pData, size * nmemb);
return nmemb;
} int curl_http::Post(std::string strUrl, std::string strPost, int& statusCode, std::string& strResponse) {
CURLcode res;
CURL* curl = curl_easy_init();
if (NULL == curl)
{
return CURLE_FAILED_INIT;
}
curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
if (list)
{
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
}
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); //验证SSL证书
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); //验证主机名的SSL
curl_easy_setopt(curl, CURLOPT_POST, 1); //发送一个HTTP POST要求
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPost.c_str()); //用这个数据发送一个POST
curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL); //读取数据回调
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData); //写入数据的回调
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse); //数据指针传递给写回调
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); //不安装信号处理程序
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3); //整个请求超时时间
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3); //连接阶段超时时间
curl_easy_setopt(curl, CURLOPT_USERAGENT, "pc_student"); //用户代理:标头
res = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &statusCode);
curl_easy_cleanup(curl);
return res;
} static size_t OnWriteFile(void* buffer, size_t size, size_t nmemb, void* lpVoid)
{
FILE* stream = (FILE*)lpVoid;
if (nullptr == stream || nullptr == buffer)
{
return -1;
}
size_t nWrite = fwrite(buffer, size, nmemb, stream);
return nWrite;
} int OnProgress(void *ptr, double totalToDownload, double nowDownloaded, double totalToUpLoad, double nowUpLoaded)
{
int tmp = 0;
long localLen = *(long*)ptr;
if ( totalToDownload > 0 )
{
tmp = (int)((nowDownloaded + (double)localLen) / (totalToDownload + (double)localLen) * 100);
}
printf("下载进度%0d%%\r", tmp);
return 0;
} size_t ProgressFunc(double* pFileLen,
double t,// 下载时总大小
double d, // 已经下载大小
double ultotal, // 上传是总大小
double ulnow) // 已经上传大小
{
if(t == 0) return 0;
*pFileLen = d;
return 0;
} curl_http_downloader::curl_http_downloader(const std::string& name)
: m_file(nullptr)
, m_TargetName(name)
, m_progress(nullptr)
{
} curl_http_downloader::~curl_http_downloader()
{
} bool curl_http_downloader::DownloadFileContent(const std::string& url,
const std::string& Targetfilepath,
const std::string& Temfilepath,
string SizeRange)
{
CURLcode res;
if(OpenFile(Temfilepath,m_file) || OpenFile(Targetfilepath,m_ExitFile))
return false; CURL* _curl = curl_easy_init(); if (nullptr == _curl)
{
CloseFile(m_file);
CloseFile(m_ExitFile);
return false;
} curl_easy_setopt(_curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(_curl, CURLOPT_WRITEFUNCTION, OnWriteFile);
curl_easy_setopt(_curl, CURLOPT_WRITEDATA, m_file);
curl_easy_setopt(_curl, CURLOPT_NOPROGRESS, false);
curl_easy_setopt(_curl, CURLOPT_PROGRESSFUNCTION, OnProgress);
curl_easy_setopt(_curl, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt(_curl, CURLOPT_LOW_SPEED_LIMIT, 1L);
curl_easy_setopt(_curl, CURLOPT_LOW_SPEED_TIME, 5L); curl_easy_setopt(_curl, CURLOPT_HEADER, 0L);
curl_easy_setopt(_curl, CURLOPT_NOBODY, 0L);
curl_easy_setopt(_curl, CURLOPT_FOLLOWLOCATION, 1L);
//curl_easy_setopt(_curl, CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t)1000); if (SizeRange == "")
curl_easy_setopt(_curl, CURLOPT_RESUME_FROM, m_LocalFilelen);
else
curl_easy_setopt(_curl, CURLOPT_RANGE, SizeRange.c_str()); curl_easy_setopt(_curl, CURLOPT_PROGRESSDATA, &m_LocalFilelen); res = curl_easy_perform(_curl); //完成curl_easy_setopt指定的所有选项,并返回状态
curl_easy_cleanup(_curl); CloseFile(m_file);
CloseFile(m_ExitFile); if (CURLE_OK == res)
return true;
else
return false;
} int curl_http_downloader::Download(const std::string& url, const std::string& path, progressFunc func,string CurrectMD5)
{
m_filePath = path; #ifdef WIN32
m_TargetFileNamepath = m_filePath + "temp.downloading";
m_Tempinterfilepath = m_filePath + "temp";
#else
m_TargetFileNamepath = m_filePath + "temp.downloading";
m_Tempinterfilepath = m_filePath + "temp";
#endif m_LocalFilelen = GetFileLength(m_TargetFileNamepath); //获取已下载文件大小
bool CricleFlags = true; //CricleFlags为dfalse时,说明下载文件错误,重新下载错误部分
bool Downloadflags = true; //Downloadflags为dfalse时,将进行下载与拼接
string range = "";
do{ bool result = DownloadFileContent(url, m_TargetFileNamepath, m_Tempinterfilepath, range);
if (result) {
std::string fullName = m_filePath + m_TargetName; if(Downloadflags)
MergerFile(m_Tempinterfilepath,m_TargetFileNamepath);
else
ToRightMergerFile(m_TargetFileNamepath, m_Tempinterfilepath); string m_fileMD5 = MD5::getFileMd5(m_TargetFileNamepath); int bmoved = 0;
#ifdef WIN32
if (_access(m_TargetFileNamepath.c_str(), 0) == 0)
remove(fullName.c_str());
#else
if (access(m_TargetFileNamepath.c_str(), 0) == 0)
remove(fullName.c_str());
#endif // WIN 32 if(CurrectMD5 == m_fileMD5){ //MD5校验
bmoved = rename(m_TargetFileNamepath.c_str(), fullName.c_str());
remove(m_Tempinterfilepath.c_str());
CricleFlags = true;
}
else{
ExchangFileName(m_Tempinterfilepath, m_TargetFileNamepath);
remove(m_Tempinterfilepath.c_str());
if((Downloadflags = !Downloadflags))
range = "";
else
range = "0-" + to_string(m_LocalFilelen-1) ;
CricleFlags = false;
}
if (bmoved) {
//std::cerr << "move file: " << m_fileNameTmp << " to: " << fullName <<" failed! ";
return -1;
}
}
else{
if(GetFileLength(m_Tempinterfilepath)){
MergerFile(m_Tempinterfilepath,m_TargetFileNamepath);
remove(m_Tempinterfilepath.c_str());
}
}
}while(!CricleFlags);
CloseFile(m_file);
CloseFile(m_ExitFile);
return 0;
} int curl_http_downloader::Pause() {
if (nullptr != m_download_info) {
m_download_info->status = PAUSED;
}
return 0;
}

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. 性能调优必备:NIO的优化实现原理

    前言 我们就从底层的网络 I/O 模型优化出发,再到内存拷贝优化和线程模型优化,深入分析下 Tomcat.Netty 等通信框架是如何通过优化 I/O 来提高系统性能的. 网络 I/O 模型优化 网络 ...

  2. Nginx 配置实例-配置高可用

    Nginx 配置实例-配置高可用 1. 实现效果 2. 两台机器 nginx 的安装 2.1 192.168.25.120 中 nginx 的安装 2.1.1 安装 pcre 依赖 2.1.2 安装其 ...

  3. TVM优化GPU机器翻译

    TVM优化GPU机器翻译 背景 神经机器翻译(NMT)是一种自动化的端到端方法,具有克服传统基于短语的翻译系统中的弱点的潜力.最近,阿里巴巴集团正在为全球电子商务部署NMT服务. 将Transform ...

  4. 视觉SLAM技术应用

    视觉SLAM技术应用 SLAM技术背景 SLAM技术全称Simultaneous localization and mapping,中文为"同时定位与地图构建".SLAM可以在未知 ...

  5. MindSpore技术理解(下)

    MindSpore技术理解(下) 4 GraphEngine 由于深度学习算法需要进行大量的计算,很多公司都设计了自己的深度学习专用处理器(如谷歌的张量处理器.阿里巴巴的含光等),华为也发布了自主设计 ...

  6. 单点突破:MySQL之索引

    前言 开发环境:MySQL5.7.31 什么是索引 在MySQL中,索引(Index)是帮助高效获取数据的数据结构. 我们可以将数据库理解为一本书,数据库中的各个数据列(column)就是目录中的章节 ...

  7. 俄罗斯方块(c++)

    这个俄罗斯方块是用c++基于windows控制台制作的. 源码地址:https://github.com/Guozhi-explore 话不多说,先上图感受一下:(控制台丑陋的界面不是我的锅emmm) ...

  8. 这应该是把Java内存区域讲的最清楚的一篇文章

    基本问题: 介绍下 Java 内存区域(运行时数据区) Java 对象的创建过程(五步,建议能默写出来并且要知道每一步虚拟机做了什么) 对象的访问定位的两种方式(句柄和直接指针两种方式) 拓展问题: ...

  9. VBS脚本编程(2)——运算符

    算数运算符 用于执行数学计算的运算符. 1.加法运算符( + ) 计算两个数之和. 2.减法运算符( - ) 计算两个数值的差或表示数值表达式的负值. 3.乘法运算符(*) 计算两个数之积. 4.除法 ...

  10. 08-ADMM算法

    08-ADMM算法 目录 一.ADMM 算法动机 二.对偶问题 三.对偶上升法 四.对偶分割 五.乘子法(增广拉格朗日函数) 5.1 步长为 $\rho$ 的好处 六.ADMM算法 6.1 ADMM ...