boost 实现http断点续传
// testc.cpp : Defines the entry point for the console application.
// #include "stdafx.h"
#include <fstream>
#include <boost/asio.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/algorithm/string.hpp> using boost::asio::ip::tcp; struct HttpResponse
{
public:
explicit HttpResponse(){ clear();}
std::string http_version; // 版本
unsigned int status_code; // 状态码
std::string status_message; // 状态
std::string header; // HTTP包头
std::string body; // HTTP返回的内容
std::string content_type;
std::string modify_time;
unsigned int content_length;
unsigned int total_length;
unsigned int offset; void clear()
{
http_version.clear();
status_code = -;
status_message.clear();
header.clear();
content_type.clear();
modify_time.clear();
content_length = ;
total_length = ;
offset = ;
body.clear();
}
}; struct DownloadInfo
{
DownloadInfo()
{
id = ;
url.clear();
filename.clear();
md5.clear();
writesize = ;
continued = false;
lasterr = ;
trycount = ;
}
int id;
std::string url;
std::string filename;
std::string md5;
int writesize;
bool continued;
int lasterr;
int trycount;
}; int GetTempFileRange( const std::string& fn );
bool GetHttpFile(const std::string& szHost, const std::string& szParam);
bool AnalyseHeader(HttpResponse& result, std::string& packetString, int nEndHeader);
bool WriteFile( const std::string& fn, int rangeStart, std::string& packetString, DownloadInfo* d_diCurrent ); std::ofstream f_ofsSave; int _tmain(int argc, _TCHAR* argv[])
{
std::string szHost ("192.168.1.102");
std::string szParam("/DoDo/aishen.mp4"); GetHttpFile(szHost, szParam); return ;
} // 获取文件
bool GetHttpFile(const std::string& szHost, const std::string& szParam)
{
// 创建下载信息
DownloadInfo* d_diCurrent = new DownloadInfo();
d_diCurrent->filename = "DownLoadFile";
d_diCurrent->continued = true; if(d_diCurrent->continued) {
d_diCurrent->filename = d_diCurrent->filename+std::string(".td");
} try
{
boost::asio::io_service io_serv; // Get a list of endpoints corresponding to the server name.
std::string szService ("http");
std::string szIp = szHost;
int i = szHost.find(":") ;
if (i != -)
{
szService = szHost.substr(i+);
szIp = szHost.substr(, i);
}
tcp::resolver::query query(szIp, szService); tcp::resolver m_resolver(io_serv);
// 创建SOCKET
tcp::socket s_socket(io_serv); tcp::resolver::iterator endpoint_iterator = m_resolver.resolve(query), end_it; // Try each endpoint until we successfully establish a connection.
tcp::resolver::iterator it = boost::asio::connect(s_socket, endpoint_iterator); if(it == end_it)
return false; boost::asio::streambuf request;
{
// 封装请求HTTP GET
std::ostream request_stream(&request); request_stream << "GET " ;
request_stream << szParam << " HTTP/1.1\r\n";
request_stream << "Host: " << szHost << "\r\n"; request_stream << "Accept: */*\r\n";
request_stream << "Pragma: no-cache\r\n";
request_stream << "Cache-Control: no-cache\r\n";
request_stream << "Connection: close\r\n"; // 1. 是否开启断点续传, 如是则读取临时文件长度
int rangeStart = ;
if (d_diCurrent->continued) {
rangeStart = GetTempFileRange(d_diCurrent->filename);
if (rangeStart) {
request_stream << "Range: bytes=" << rangeStart << "- \r\n";
}
request_stream << "\r\n";
} boost::asio::write(s_socket, request); boost::asio::streambuf response;
std::ostringstream packetStream;
try
{
// Read until EOF, writing data to output as we go.
bool hasReadHeader = false; boost::system::error_code error; HttpResponse result;
result.body.clear(); while (boost::asio::read(s_socket, response,
boost::asio::transfer_at_least(), error))
{
packetStream.str("");
packetStream << &response; std::string packetString = packetStream.str(); // 2. 是否已分析文件头
if (!hasReadHeader)
{
hasReadHeader = true;
// 取出http header
size_t nEndHeader = packetString.find("\r\n\r\n");
if(nEndHeader == std::string::npos)
continue; if(!AnalyseHeader(result, packetString, nEndHeader)) {
return false;
}
} // 3. 写入文件
WriteFile(d_diCurrent->filename, rangeStart, packetString, d_diCurrent);
} // 4. 关闭文件
f_ofsSave.close(); // 5. 文件改名
std::string fn = "DownLoadFile.db";
rename(d_diCurrent->filename.c_str(), fn.c_str()); if (error != boost::asio::error::eof)
throw boost::system::system_error(error); }
catch (std::exception& e)
{
std::cout << "Exception: " << e.what() << "\n";
return false;
}
}
}
catch(std::exception& e) {
std::cout << "Exception: " << e.what() << "\n";
return false;
} return true;
} // *****************************************************
// 分析文件头
// *****************************************************
bool AnalyseHeader(HttpResponse& result, std::string& packetString, int nEndHeader)
{
result.header = packetString.substr(, nEndHeader); // Check that response is OK.
std::istringstream response_stream(result.header);
response_stream >> result.http_version;
response_stream >> result.status_code; std::string strLine;
std::getline(response_stream, strLine);
while (!strLine.empty())
{
if (strLine.find("Content-Type:") != std::string::npos)
{
result.content_type = strLine.substr(strlen("Content-Type:"));
result.content_type.erase(, result.content_type.find_first_not_of(" "));
}
if (strLine.find("Content-Length:") != std::string::npos)
{
result.content_length = atoi(strLine.substr(strlen("Content-Length:")).c_str());
result.total_length = result.content_length;
}
if (strLine.find("Last-Modified:") != std::string::npos)
{
result.modify_time = strLine.substr(strlen("Last-Modified:"));
result.modify_time.erase(, result.modify_time.find_first_not_of(" "));
}
if (strLine.find("Content-Range: bytes") != std::string::npos)
{
std::string tmp = strLine.substr(strlen("Content-Range: bytes"));
result.offset = atoi(tmp.substr(, tmp.find('-')).c_str());
int ipos = tmp.find('/');
int ivalue = ;
if (ipos != std::string::npos)
{
ivalue = atoi(tmp.substr(ipos+).c_str());
}
if (ivalue)
result.total_length = ivalue;
}
strLine.clear();
std::getline(response_stream, strLine);
} if ( result.http_version.substr(, ) != "HTTP/")
{
std::cout << "Invalid response\n";
return false;
}
if (result.status_code != && result.status_code != )
{
std::cout << "Response returned with status code "
<< result.status_code << "\n";
return false;
} packetString.erase(, nEndHeader + ); return true;
} // **************************************************************
// 获取临时文件大小
// **************************************************************
int GetTempFileRange( const std::string& fn )
{
int rangeStart = ;
std::ifstream ifs;
ifs.open(fn, std::ios_base::in | std::ios_base::binary );
if (ifs.is_open()) {
ifs.seekg(, std::ios::end);
rangeStart = ifs.tellg();
}
ifs.close(); return rangeStart;
} // **************************************************************
// 写入文件
// **************************************************************
bool WriteFile( const std::string& fn, int rangeStart, std::string& packetString, DownloadInfo* d_diCurrent )
{
if (!f_ofsSave.is_open())
{
if (d_diCurrent->continued)
{
f_ofsSave.open(fn, std::ios_base::out | std::ios_base::binary | std::ios_base::app );
if (f_ofsSave.is_open())
{
f_ofsSave.seekp(rangeStart);
d_diCurrent->writesize += rangeStart;
//int range = f_ofsSave.tellp();
}
}
else
{
f_ofsSave.open(fn, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc );
} if (!f_ofsSave.is_open())
{
return false;
} d_diCurrent->writesize = ;
} try {
f_ofsSave.write(packetString.c_str(), packetString.length());
d_diCurrent->writesize += packetString.length();
}
catch (std::exception &e)
{
return false;
} std::cout << " write size = "<<d_diCurrent->writesize<<"\n"; return true;
}
boost 实现http断点续传的更多相关文章
- boost强分类器的实现
boost.cpp文件下: bool CvCascadeBoost::train( const CvFeatureEvaluator* _featureEvaluator, int _numSampl ...
- HTML5实现文件断点续传
HTML5的FILE api,有一个slice方法,可以将BLOB对象进行分割.前端通过FileList对象获取到相应的文件,按照指定的分割方式将大文件分段,然后一段一段地传给后端,后端再按顺序一段段 ...
- Boost信号/槽signals2
信号槽是Qt框架中一个重要的部分,主要用来解耦一组互相协作的类,使用起来非常方便.项目中有同事引入了第三方的信号槽机制,其实Boost本身就有信号/槽,而且Boost的模块相对来说更稳定. signa ...
- 总结iOS开发中的断点续传那些事儿
前言 断点续传概述 断点续传就是从文件赏赐中断的地方重新开始下载或者上传数据,而不是从头文件开始.当下载大文件的时候,如果没有实现断点续传功能,那么每次出现异常或者用户主动的暂停,都会从头下载,这样很 ...
- 玩转Windows服务系列——使用Boost.Application快速构建Windows服务
玩转Windows服务系列——创建Windows服务一文中,介绍了如何快速使用VS构建一个Windows服务.Debug.Release版本的注册和卸载,及其原理和服务运行.停止流程浅析分别介绍了Wi ...
- (实例篇)PHP实现HTTP断点续传的方法
PHP实现HTTP断点续传的方法. <?php /** * PHP-HTTP断点续传实现 * @param string $path: 文件所在路径 * @param string $file: ...
- boost::function的用法
本片文章主要介绍boost::function的用法. boost::function 就是一个函数的包装器(function wrapper),用来定义函数对象. 1. 介绍 Boost.Func ...
- C# 文件下载之断点续传
注意,本文所说的断点续传特指 HTTP 协议中的断点续传.本文主要聊聊思路和关键代码,更多细节请参考本文附带的 demo. 工作原理 HTTP 协议中定义了一些请求/响应头,通过组合使用这些头信息.我 ...
- Boost条件变量condition_variable_any
Boost条件变量可以用来实现线程同步,它必须与互斥量配合使用.使用条件变量实现生产者消费者的简单例子如下,需要注意的是cond_put.wait(lock)是在等待条件满足.如果条件不满足,则释放锁 ...
随机推荐
- 安装saltstack使用的shell
sed -i 's/^#//g' /etc/yum.repos.d/centos6.8.repo sed -i 's/enabled=0/enabled=1/g' /etc/yum.repos.d ...
- ASP.NET的checkboxlist,RadioButtonList,FileUpload,image控件的综合使用
一.拖控件 控件拖完如图所示:(有些是对不齐的,加一个表单就好了,把他们都放在表单里) 单纯的RadioButton是不能只选择一个的,除非你手动给他们加上代码: RadioButton1.Group ...
- JMX监控Hadoop的部分常用参数位置
近期版本get无法使用,可能使用了其他参数代替,但源码中已经去掉JMX部分,也没有给出替代接口,应该是不再额外实现了. NameNode DataNode HDFS Yarn HBase MapRed ...
- canvas.drawImage()方法详解
首先看html5.js /**@param {Element} img_elem@param {Number} dx_or_sx@param {Number} dy_or_sy@param {Numb ...
- mysql关联模糊查询他表字段
如下:订单表关联了用户的id(多个),要根据用户名模糊查询订单信息,但是订单表只有id.创建视图用不着,咱也没权限.于是如下 SELECT * FROM ( SELECT cu.id AS 'id', ...
- std::rotate使用
1. 进行元素范围上的左旋转 first - 原范围的起始 n_first - 应出现在旋转后范围起始的元素 last - 原范围的结尾 原来:1 2 3 左旋转后(起始元素是2) : 2 3 1
- 052、overlay如何实现跨主机通信?(2019-03-19 周二)
参考https://www.cnblogs.com/CloudMan6/p/7305989.html 今天开始学习 overlay 网络跨主机通信的原理 root@host01:~# ufw ...
- Linux下的解压命令
Linux下常见的压缩包格式有5种:zip tar.gz tar.bz2 tar.xz tar.Z 其中tar是种打包格式,gz和bz2等后缀才是指代压缩方式:gzip和bzip2 filename. ...
- Android文字转语音引擎(TTS)使用
百度网盘下载地址 密码:3si0资源来源:https://blog.csdn.net/Sqq_yj/article/details/82460580?utm_source=blogxgwz4 简单比较 ...
- ffmpeg安装
使用 yum 安装nux-dextop 源. 下载:wget http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0- ...