HTTP传输大文件

Android_Banner.jpg

我们知道HTTP报文中的body不仅可以传输文本还可以传输图片、视频以及音频;

随着互联网的发展,现在随便一个HTML文件就有几百KB,如果是高质量的图片或者视频那都要M或者GB了;

我们的带宽都是固定在这些大文件面前就显的微不足道;

接下来我们就看看在HTTP协议加持下是如何在固定宽带的情况下传输这些超大文件的

数据压缩

在【HTTP Body】一文中我们介绍【数据类型与编码】中就有关于针对body报文的压缩

我们在请求头字段中使用【Accept-Encoding: gzip】告知服务器我们能接受gzip压缩类型的数据;

同时在响应头中使用【Content-Encoding:gzip】和body中把数据传递给客户端;

【数据压缩】就是把我们巨大的数据量【成年的猪猪】---> 【幼年的小猪羔子】然后在回传给客户端;

不过gzip这种压缩针对文本压缩还是很有效果的;对于图片或者音频来说,本身也是经过处理的了使用gzip的收益不大;

不过在传输文本的时候服务器还是会使用gzip作为一次【保底】;

除了压缩数据之外,HTTP还是支持分块传输的;

分块传输

分块传输也就是把数据切成很多块,分批传递给客户端客户端收到后在重新组装,思想就是减少每次数据的传输量;

在HTTP协议头字段中,针对分块传输的表现是使用【Transfer-Encoding:chunked】表示响应报文body中的数据不是一次性全部传递过来的,而是分成很多块逐个发送的;

分块传输也可以用于【流式数据】;例如数据库动态生成的表单页面;这种情况下body数据的长度是未知,那么头字段中【Content-Length】无法给出确切的长度

换句话说,在响应报文中【Content-Length】和【Transfer-Encoding:chunked】不能同时出现;一个响应报文长度要么是【已知】的要么是【未知】的;

分块传输的规则
  • 每个分块包含两个部分。长度头和数据块;

  • 长度头是以CRLF(回车换行,即\r\n)结尾的一行明文,用16进制数字表示长度;

  • 数据块在长度头之后,最后用CRLF结尾,数据块不包含CRLF

  • 最后用一个长度为0的块表示结束,即【0\r\n\r\n】

HTTP中body的分块传输.png

范围请求

使用场景
  • 当我们观看一部电影时,去跳过片头时(拖拽进度条前进),使用到了范围请求;

    这个实际上是获取一个大文件其中的片段数据;我们的分块传输并没有这个能力;

任何技术的出现都是为了满足用户需求出现的,范围请求就是为了解决上述类似场景的需求;

HTTP协议允许客户端在请求头里使用专用字段获取文件的一部分;

范围请求不是WEB服务器必备的功能;服务器可以在响应头字段中使用【Accept-Ranges:bytes】明确告知客户端我是不是支持的

不支持
  • 不支持:服务器就返回【Accept-Ranges:none】或者就不返回对应的字段;
支持

【Range】是HTTP范围请求中请求头的专用字段,格式是【bytes=x-y】x和y是以字节为单位的数据范围;

范围必须从0计数【0-9】表示前10个字节,【10-19】表示第二个10字节;

灵活的Range格式

【0-】表示从数据起点到终点,表示整个文件

【10-】表示从第10个字节开始到文档结尾;

【-1】表示最后一个字节;

【-10】表示文档末尾倒数10个字节;

服务器收到Range的处理

  • 检查范围的合法性,如果范围越界了,服务器就会返回状态码【416】;

  • 范围正确的话,就根据Range头计算返回数据的片段;此时的状态码为【206 Partial Content】

  • 同时服务器会在响应头字段中添加一个【Content-Range】告诉片段的实际偏移量和资源的总大小

    • 这里在说下,响应头中会返回【Accept-Range】用于告知服务器是否支持范围请求的;

响应头中的【Content-Range】

格式是 【bytes x-y/length】与请求头中的Range区别在于没有【=】,范围区间后多了【总长度length】

应用场景
  • 视频拖拽进度

  • 下载工具里的多段下载,断点续传

大概思路

  • 发送一个HEAD请求,查看服务器是否支持范围请求,同时能获取到文件的大小

  • 开启线程,线程中发起的网络请求使用Range字段划分出各自负责的下载的片段;

多段数据

上文说的范围请求一次只能获取一个数据片段,当在请求头【Range】中使用多个【x-y】就能一次性获取多个片段数据了,也就是【多段数据】

上述【多段数据】使用情况使用特殊的MIME 【multipart/byteranges】表示响应报文中body是由多段数据组成的;

同时使用【boundary=xxx】标识出每段之间的分隔标记;

直接上示意图

HTTP中的body-多段数据是以图.png
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容