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)是在等待条件满足.如果条件不满足,则释放锁 ...
随机推荐
- 【C#】C#创建自定义Object对象
艹,老是忘!!! }; 记录一下,var obj = new { Name="lily",Age=12};
- setAttribute和setParameter方法的区别
getAttribute表示从request范围取得设置的属性,必须要先setAttribute设置属性,才能通过getAttribute来取得,设置与取得的为Object对象类型 getParame ...
- ffmpeg的各种黑科技
获取音频的时长 /** * 获取视频文件的时长 * @param ffmpegPath 是ffmpeg软件存放的目录,sourceFile是目标文件 * @return */ public Strin ...
- Kafka权威指南 读书笔记之(五)深入Kafka
集中讨论以下3 个有意思的话题 :• Kafka 如何进行复制:• Kafka 如何处理来自生产者和消费者的请求 :• Kafka 的存储细节,比如文件格式和索引. 集群成员关系 Kafka 使用 Z ...
- Linux记录-CPU指标介绍
在linux的系统维护中,可能需要经常查看cpu使用率,分析系统整体的运行情况.而监控CPU的性能一般包括以下3点:运行队列.CPU使用率和上下文切换. 对于每一个CPU来说运行队列最好不要超过3,例 ...
- [Android] Android 使用Greendao gradle 出现 Error:Unable to find method 'org.gradle.api.tasks.TaskInputs.file(Ljava/lang/Object;)
Android 使用Greendao gradle 出现 Error:Unable to find method 'org.gradle.api.tasks.TaskInputs.file(Ljava ...
- SpringBoot系列: logging
我们的 SpringBoot 程序都会加 spring-boot-starter 包, 而该包一个依赖项 spring-boot-starter-logging, 所以SpringBoot 程序不需要 ...
- mkdocs 生成帮助文档
简介 MkDocs 可以同时编译多个markdown文件,形成书籍一样的文件.有多种主题供你选择,很适合项目使用. MkDocs 是快速,简单和华丽的静态网站生成器,可以构建项目文档.文档源文件在 M ...
- PHP 调第三方跨域接口示例
<?php ); //错误信息 ); //php启动错误信息 ini_set('date.timezone','Asia/Shanghai'); ); //打印出所有的 错误信息 ini_set ...
- Java EE之Hibernate异常总结org.hibernate.MappingException: Repeated column in mapping for entity:
解决方案/原因: 一个pojo(JavaBean)中不能有两个属性同时映射到一个数据库字段上 即使是一个属性的两个getter方法也不行 %%%% Error Creating SessionFact ...