// 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断点续传的更多相关文章

  1. boost强分类器的实现

    boost.cpp文件下: bool CvCascadeBoost::train( const CvFeatureEvaluator* _featureEvaluator, int _numSampl ...

  2. HTML5实现文件断点续传

    HTML5的FILE api,有一个slice方法,可以将BLOB对象进行分割.前端通过FileList对象获取到相应的文件,按照指定的分割方式将大文件分段,然后一段一段地传给后端,后端再按顺序一段段 ...

  3. Boost信号/槽signals2

    信号槽是Qt框架中一个重要的部分,主要用来解耦一组互相协作的类,使用起来非常方便.项目中有同事引入了第三方的信号槽机制,其实Boost本身就有信号/槽,而且Boost的模块相对来说更稳定. signa ...

  4. 总结iOS开发中的断点续传那些事儿

    前言 断点续传概述 断点续传就是从文件赏赐中断的地方重新开始下载或者上传数据,而不是从头文件开始.当下载大文件的时候,如果没有实现断点续传功能,那么每次出现异常或者用户主动的暂停,都会从头下载,这样很 ...

  5. 玩转Windows服务系列——使用Boost.Application快速构建Windows服务

    玩转Windows服务系列——创建Windows服务一文中,介绍了如何快速使用VS构建一个Windows服务.Debug.Release版本的注册和卸载,及其原理和服务运行.停止流程浅析分别介绍了Wi ...

  6. (实例篇)PHP实现HTTP断点续传的方法

    PHP实现HTTP断点续传的方法. <?php /** * PHP-HTTP断点续传实现 * @param string $path: 文件所在路径 * @param string $file: ...

  7. boost::function的用法

    本片文章主要介绍boost::function的用法. boost::function 就是一个函数的包装器(function wrapper),用来定义函数对象. 1.  介绍 Boost.Func ...

  8. C# 文件下载之断点续传

    注意,本文所说的断点续传特指 HTTP 协议中的断点续传.本文主要聊聊思路和关键代码,更多细节请参考本文附带的 demo. 工作原理 HTTP 协议中定义了一些请求/响应头,通过组合使用这些头信息.我 ...

  9. Boost条件变量condition_variable_any

    Boost条件变量可以用来实现线程同步,它必须与互斥量配合使用.使用条件变量实现生产者消费者的简单例子如下,需要注意的是cond_put.wait(lock)是在等待条件满足.如果条件不满足,则释放锁 ...

随机推荐

  1. C# 主动发起请求代码

    本文用于写代码是给提示 private string GetHW(string uri) { string returnStr = ""; HttpWebRequest hwReq ...

  2. 利用css3给座右铭设置漂亮的渐变色

    .footer-container .footer-content p .motto { font-weight: bolder; -webkit-background-clip: text; -we ...

  3. layui(四)——table组件常见用法总结

    table是 layui 最核心的组成之一.它用于对表格进行一些列功能和动态化数据操作,涵盖了日常业务所涉及的几乎全部需求.支持固定表头.固定行.固定列左/列右,支持拖拽改变列宽度,支持排序,支持多级 ...

  4. VS2015快捷键大全

    Ctrl+E,D —-格式化全部代码 Ctrl+E,F —-格式化选中的代码 CTRL + SHIFT + B生成解决方案 CTRL + F7 生成编译 CTRL + O 打开文件 CTRL + SH ...

  5. HTML5 离线缓存Appcache

    创建一个和html同名的manifest文件,比如页面为index.html,那么可以建一个index.manifest的文件,然后给index.html的html标签添加如下属性即可: <ht ...

  6. 阅读:ECMAScript 6 入门(1)

    参考 ECMAScript 6 入门 ES6新特性概览 ES6 全套教程 ECMAScript6 (原著:阮一峰) JavaScript 教程 重新介绍 JavaScript(JS 教程) 前言 学了 ...

  7. 解析ArcGis的标注(三)——标注的放置 与 转注记修改

    该“标注”系列博文的标注引擎使用“标准标注引擎(standard label engine)”,这个概念如不知道,可不理会,ArcGis默认标注引擎就是它. 写着写着发现ArcGis标注的破事儿好多啊 ...

  8. [Android] Android利用Coordinatorlayout+AppbarLayout实现折叠式布局

    折叠式布局在App中相当常见,给人一种科技感,充满良好的用户体验. 本文就以两个简单的例子,来举例说明基本折叠式布局: 首先需要在app/build.gradle下添加如下依赖: compile 'c ...

  9. 1、PHP入门二维数组与循环

    <?php $two=array(array(2,3),1=>array(1,2,3),2=>array(4,5,6)); echo $two[1][0];//输出1 echo $t ...

  10. 使用js弹出div刷新时闪烁解决方法

    <div style="visibility: hidden"> //弹出div内容 </div>