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)是在等待条件满足.如果条件不满足,则释放锁 ...
随机推荐
- passat QA / error code 20190210
s 帕萨特B5 技术资料下载 https://pan.baidu.com/s/1KXYly7eGDUSI5QiLcz8fiQ 提取码: 1i7u 星期日,10,二月,2019,17:16:16:317 ...
- CentOS7 下 Hadoop 分布式部署
Hadoop 服务划分 使用三台节点,集群部署规划如下 服务\主机 hadoop1 hadoop2 hadoop3 HDFS NameNode DataNode DataNode SecondaryN ...
- Oracle和Mysql的安装
Oracle12C的安装:https://blog.csdn.net/qubeleyz/article/details/79451192 Mysql安装:
- 自学python 2.
1.T or F 1>1 or 3<4 or 4>5 and 2>1 and 9>8 or 7<6 t not 2>1 and 3<4 or 4> ...
- C#中转换函数Convert、Parse、TryParse、(int) 的区别
Convert.Parse.TryParse.(int) 三个函数都是将值转换成整数,但是四者之间各有异同,开发人员可以根据情况选用最合适的.以下解释均经过高人验证,希望对大家有所帮助. 1 (int ...
- 微信接口 output {"errMsg":"translateVoice:fail, the permission value is offline verifying"}
jsApiList : [ 'checkJsApi', 'startRecord', 'stopRecord','translateVoice','scanQRCode', 'openCard' ]增 ...
- ****** 三十四 ******、软设笔记【存储器系统】-Cache存储器
Cache存储器 Cache(高速缓冲存储器) 高速缓冲存储器是位于主存与CPU之间的一级存储器,有静态存储芯片(SRAM)组成,容量比较小,速度比主存高得多,接近于CPU的速度,单位成本比内存高.C ...
- MySQL Out-of-Band 攻击
概述 当涉及到MSSQL与Oracle时,Out-of-Band 注入是非常好的方式.但我注意到MySQL注入的情况并非如此,于是我准备以自己在SQL注入方面的经验做相关的研究.我们可以利用诸如loa ...
- springboot 02-PropertiesFile 自定义配置属性,多环境配置
application.properties: # 自定义配置 test.hello.world = HelloWorld test.person.name = 哈哈 test.person.sex ...
- excel数据处理,公式
1. 替换 SUBSTITUTE(字符串, 原字符串, 新字符串) =SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(L2,"镇",""),& ...