当前位置: 首页 > news >正文

C++第三方库【httplib】断点续传

什么是断点续传

上图是我们平时在浏览器下载文件的场景,下载的本质是数据的传输。当出现网络异常,浏览器异常,或者文件源的服务器异常,下载都可能会终止。而当异常解除后,重新下载文件,我们希望从上一次下载的位置开始下载,而不是从头开始下载。这就是断点续传

断点续传的实现

ETag头部字段

ETag是用来标识文件的头部字段,由用户自己设定,其目的是表示文件的唯一性,修改过的文件和原文件是不同的。

ETag由服务端设置

static void download(const httplib::Request& req, httplib::Response& resp)
{//......//服务端设置ETag头部字段resp.set_header("ETag", "......");//......
}

浏览器解析响应,发现有ETag字段,保存并在下次发送GET请求时包含。ETag搭配Range字段实现断点续传

Range

当服务端返回的响应中有Accept-Ranges头部字段,代表服务端允许断点续传

客户端此时发送的请求可以携带Range头部字段,形式如下:

//服务端响应设置允许断点续传
static void download(const httplib::Request& req, httplib::Response& resp)
{//......//bytes表示客户端数据请求区间的单位resp.set_header("Accept-Ranges", "bytes");//......
}//客户端请求断点续传区间
static void download(const httplib::Request& req, httplib::Response& resp)
{//......//val是服务端上一次发送的ETagres.set_header("If-Range", ETag);//val的bytes是服务端返回的断点区间的单位//start-end代表重传start到end区间的数据,比如5430-66758res.set_header("Range", "bytes=start-end");//......
}//服务端返回响应
static void download(const httplib::Request& req, httplib::Response& resp)
{//......//响应的文件数据范围是start-end,文件总大小为fsizeresp.set_header("Content-Range, "start-end/fsize");//重新设置ETagresp.set_header("ETag", "......");//......
}
  • 服务端设置Accept-Range字段,val值一般为bytes。该字段表示服务端支持断点续传,以字节单位传输数据
  • ETag表示服务端上某一版本资源的唯一标识,如果资源被改动,则ETag改变。客户端收到ETag表示会保存

当下载中断时,浏览器重新下载文件,则第二次的http请求需要包含If-Range字段和Range字段

  • If-Range字段:保存服务端响应的ETag字段的信息。用于服务端判断是否和上一次请求的资源一致,一致则断点续传,不一致则从头重新下载
  • Range字段:记录断点请求的数据区间,bytes start-end,表示请求服务器资源从第start字节开始到第end个字节的数据

收到客户端发送的断点续传的http响应,需要包含Content-Range字段和ETag字段4

  • Content-Range: start-end/文件大小,表示http响应包含文件数据从start开始到end结束的文件数据,文件大小表示文件总大小
  • ETag:服务端资源的唯一标识

当服务端返回的数据是断点续传的数据区间时,状态码是206

示例断点续传的请求&响应如下:

GET /download/a.txt http/1.1
If-Range: "文件唯一标识"
Range: bytes=89-999
-------------------------------------------
HTTP/1.1 206 Partial Content
Accept-Ranges: bytes
Content-Range: bytes 89-999/100000
Content-Type: application/octet-stream
ETag: "文件唯一标识"对应文件从89到999字节的数据。

编码实现

使用httplib实现断点续传。

基本逻辑:

  1. 查看客户端请求是否包含If-Range字段,有则匹配请求文件的ETag,没有则是正常下载文件
  2. 若相同,说明客户端请求断点续传,解析Range字段,将start-end的数据填入响应的正文部分。并设置头部字段
  3. 若不同,说明客户端请求的数据被修改了,则需要从头下载,返回文件全部数据。并设置头部字段

以上逻辑,我们需要手动解析客户端响应的Range字段,但httplib已经帮我们解析了,以下源码是httplib做的部分处理

这部分表示,httplib解析客户端请求,如果包含Range字段,会自动设置响应的状态码为206

这部分是httplib解析Range字段,在返回文件数据时,会根据Range字段的解析结果,截断文件数据。所以我们在代码编写时不管是正常下载,还是断点续传都直接响应文件全部数据即可, 如果是断点续传,httplib会帮我们进行数据截断,如果start-end是5430-66347,就截出这部分数据返回给客户端

示例代码如下:

//生成ETag
//ETag = 文件名 + 文件大小 + 文件最后一次修改时间
static std::string getETag(const std::string& filename, const struct stat st)
{std::string ETag;ETag = filename + std::to_string(st.st_size) + std::to_string(st.m_tim);return ETag;
}    //返回客户端要下载的文件
static void download(const httplib::Request& req, httplib::Response& resp)
{//1. 获取客户端请求的资源路径:req.path。截取最后一个/后的字符串,为文件名//2. 根据资源路径,获取文件信息auto pos = req.path.find_last_of('/');std::string filenameif(pos == std::string::npos)filename = req.path;elsefilename = req.path.substr(pos + 1);struct stat st;stat(filename.c_str(), &st);//查看请求是否有If-Range(记录之前服务器响应的ETag)bool retrans = true;std::string old_etag;//有If-Range,两种可能:有修改,全部重传;没有修改,断点续传if(req.has_header("If-Range")){old_etag = req.get_header_value("If-Range");if(old_etag == getETag(info, st))retrans = false;}//4. 读取文件信息到响应中std::ifstream ifs(filename.c_str(), std::ios::binary);//读取文件内容body.resize(st.s_size);ifs.read(&body[0], st.s_size);//5. 设置头部字段resp.set_header("ETag", getETag(info, st));resp.set_header("Accept-Ranges", "bytes");//提供断点续传resp.set_header("Content-Type", "application/octet-stream");//下载文件if(retrans){//文件有修改,需要重传文件//ETag  Accept-Ranges bytes(断点续传)resp.status = 200;}else{//断点续传实现:获取头部字段中Range:bytes start-end,解析请求文件的起始和结束//再返回响应时,对文件内容进行截断//但httplib都实现了,他检测到req中有Range,然后进行处理,甚至会设置resp的状态码//我们只要返回完整的文件,httplib会对文件进行截断,最后响应正文中只有start-end的文件内容//resp.set_header("Content-Range", "bytes start-end/fsize");//原本还要设置这个头部字段,httplib帮我们做了resp.status = 206;//断点续传的状态码}
}

相关文章:

C++第三方库【httplib】断点续传

什么是断点续传 上图是我们平时在浏览器下载文件的场景,下载的本质是数据的传输。当出现网络异常,浏览器异常,或者文件源的服务器异常,下载都可能会终止。而当异常解除后,重新下载文件,我们希望从上一次下载…...

[SaaS] AI+数据,tiktok选品,找达人,看广告数据

TK观察专访丨前阿里“鲁班”创始人用AIGC赋能TikTok获千万融资用AI数据做TikTokhttps://mp.weixin.qq.com/s/xp5UM3ROo48DK4jS9UBMuQ主要还是爬虫做数据的。 商家做内容:1.找达人拍内容,2.商家自己做原生自制内容,3.广告内容。 短视频&…...

A股冲高回落,金属、地产板块领跌,新股N汇成真首日暴涨753%

行情概述 AH股有色金属、教育及地产板块领跌,军工航天及半导体板块逆势走强;锂电池、创新药概念股也走强。创业板新股N汇成真首日暴涨753%,触发二次临停。 周三A股冲高回落,上证指数收跌0.83%,深成指跌0.8%&#xff…...

dns域名解析服务和bond网卡

目录 dns域名解析服务 一、DNS 1、定义 2、以www.baidu.com为例 3、域名体系结构 4、DNS解析使用的协议和端口 5、dns域名解析的过程 6、dns解析的优先级 二、如何实现域名解析 1、域名解析 2、bind配置文件位置 (一)正向解析 (…...

视频生成框架EasyAnimate正式开源!

近期,Sora模型的热度持续上涨,社区中涌现了一些类Sora的开源项目,这些项目均基于Diffusion Transformer结构,使用Transformer结构取代了UNet作为扩散模型的基线,旨在生成更长、更高分辨率、且效果更好的视频。EasyAnim…...

【微机原理与汇编语言】并行接口8255实验

一、实验目的 掌握可编程并行接口芯片8255的工作原理及初始化方法掌握8255在实际应用中的硬件连接及编程应用 二、实验要求 根据实验室现有条件,针对实验任务,设计实验方案并进行实现。 三、实验内容 启动0#计数器,每计5个数&#xff08…...

Oracle表分区的基本使用

什么是表空间 是一个或多个数据文件的集合,所有的数据对象都存放在指定的表空间中,但主要存放的是表,所以称为表空间 什么是表分区 表分区就是把一张大数据的表,根据分区策略进行分区,分区设置完成之后,…...

6月5号作业

设计一个Per类&#xff0c;类中包含私有成员:姓名、年龄、指针成员身高、体重&#xff0c;再设计一个Stu类&#xff0c;类中包含私有成员:成绩、Per类对象p1&#xff0c;设计这两个类的构造函数、析构函数 ​ #include <iostream>using namespace std; class Slu { priv…...

中继器、集线器、网桥、交换机、路由器和网关

目录 前言一、中继器、集线器1.1 中继器1.2 集线器 二、网桥、交换机2.1 网桥2.1.1 认识网桥2.1.2 网桥的工作原理2.1.3 生成树网桥 2.2 交换机2.2.1 交换机的特征2.2.2 交换机的交换模式2.2.3 交换机的功能 三、路由器、网关3.1 路由器的介绍3.2 路由器的工作过程3.2.1 前置知…...

揭秘相似矩阵:机器学习算法中的隐形“纽带”

在机器学习领域&#xff0c;数据的处理和分析至关重要。如何有效地从复杂的数据集中提取有价值的信息&#xff0c;是每一个机器学习研究者都在努力探索的问题。相似矩阵&#xff0c;作为衡量数据之间相似性的数学工具&#xff0c;在机器学习算法中扮演着不可或缺的角色。 相似矩…...

攻防世界—webbaby详解

1.ssrf注入漏洞 ssrf&#xff08;服务端请求伪造&#xff09;是一种安全漏洞&#xff0c;攻击者通过该漏洞向受害服务器发出伪造的请求&#xff0c;从而访问并获取服务器上的资源&#xff0c;常见的ssrf攻击场景包括访问内部网络的服务&#xff0c;执行本地文件系统命令&#…...

MySQL中:cmd下输入命令mysql -uroot -p 连接数据库错误

目录 问题cmd下输入命令mysql -uroot -p错误 待续、更新中 问题 cmd下输入命令mysql -uroot -p错误 解决 配置环境变量&#xff1a;高级系统设置——环境变量——系统变量——path编辑——新建——MySQL.exe文件路径&#xff08;如下图所示&#xff09; phpstudy2018软件下&am…...

【开发利器】使用OpenCV算子工作流高效开发

学习《人工智能应用软件开发》&#xff0c;学会所有OpenCV技能就这么简单&#xff01; 做真正的OpenCV开发者&#xff0c;从入门到入职&#xff0c;一步到位&#xff01; OpenCV实验大师Python SDK 基于OpenCV实验大师v1.02版本提供的Python SDK 实现工作流导出与第三方应用集…...

基础数学-求平方根(easy)

一、问题描述 二、实现思路 1.题目不能直接调用Math.sqrt(x) 2.这个题目可以使用二分法来缩小返回值范围 所以我们在left<right时 使 mid (leftright)/21 当mid*mid>x时&#xff0c;说明right范围过大&#xff0c;rightright-1 当mid*mid<x时&#xff0c;说明left范…...

c语言项目-贪吃蛇项目2-游戏的设计与分析

文章目录 前言游戏的设计与分析地图&#xff1a;这里简述一下c语言的国际化特性相关的知识<locale.h> 本地化头文件类项setlocale函数 上面我们讲到需要打印★&#xff0c;●&#xff0c;□三个宽字符找到这三个字符打印的方式有两种&#xff1a; 控制台屏幕的长宽特性&a…...

力扣2831.找出最长等值子数组

力扣2831.找出最长等值子数组 思路&#xff1a;用二维数组存每个数字的出现下标 遍历所有数字求结果当前子数组大小&#xff1a;pos[i] - pos[j] 1;当前相同数个数&#xff1a;i - j 1;需要删去的数的个数&#xff1a;pos[i] - pos[j] - i j; class Solution {public:int…...

17K star,一款开源免费的手机电脑无缝同屏软件

导读&#xff1a;白茶清欢无别事&#xff0c;我在等风也等你。 作为程序员&#xff0c;在我们的工作中经常需要把手机投票到电脑进行调试工作&#xff0c;选择一款功能强大的投屏软件是一件很必要的事情。今天给大家介绍一款开源且免费的投屏软件&#xff0c;极限投屏&#xff…...

正则表达式二

修饰符 i&#xff1a;将匹配设置为不区分大小写&#xff0c;即A和a没有区别 var str"Google Runoob taobao runoob"; var n1str.match(/runoob/g); //runoob var n2str.match(/runoob/gi); //Runoob&#xff0c;runoobg&#xff1a;重找所有匹配项&#xff0…...

我的创作纪念日--我和CSDN一起走过的1825天

机缘 第一次在CSDN写文章&#xff0c;是自己在记录学习Java8新特性中Lambda表达式的内容过程中收获的学习心得。之前也有记录工作和生活中的心得体会、难点的解决办法、bug的排查处理过程等等。一直都用的有道笔记&#xff0c;没有去和大家区分享的想法&#xff0c;是一起的朋…...

递归书写树形图示例

大叫好&#xff0c;今天书写了一个扁型转换为树型的例子&#xff0c;使用的是递归&#xff0c;请大家食用&#xff0c;无毒 <!DOCTYPE html> <html lang"zh"><head><meta charset"UTF-8"><meta name"viewport" conte…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄

文&#xff5c;魏琳华 编&#xff5c;王一粟 一场大会&#xff0c;聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中&#xff0c;汇集了学界、创业公司和大厂等三方的热门选手&#xff0c;关于多模态的集中讨论达到了前所未有的热度。其中&#xff0c;…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

可靠性+灵活性:电力载波技术在楼宇自控中的核心价值

可靠性灵活性&#xff1a;电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中&#xff0c;电力载波技术&#xff08;PLC&#xff09;凭借其独特的优势&#xff0c;正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据&#xff0c;无需额外布…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台

🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

#Uniapp篇:chrome调试unapp适配

chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器&#xff1a;Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...

面向无人机海岸带生态系统监测的语义分割基准数据集

描述&#xff1a;海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而&#xff0c;目前该领域仍面临一个挑战&#xff0c;即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...