12 HTTP传输大文件

Posted by CodingWithAlice on April 25, 2021

12 HTTP传输大文件

  • 总结

    1、压缩 HTML 等文本文件是传输大文件最基本的方法

    2、分块传输 可以流式收发数据,节约内存和带宽,使用响应头字段 Transfer-Encoding: chunked 来表示,分块的格式是 16 进制长度头 + 数据块;

    3、范围请求 可以只获取部分数据,即 分块请求,实现 视频拖拽或者断点续传,使用请求头字段 Range 和响应头字段 Content-Range,响应状态码必须是 206;

    4、也可以一次 请求多个范围,这时候响应报文的数据类型是 multipart/byterangesbody 里的多个部分会用 boundary 字符串分隔

1/4、数据压缩

  • 优点

    如果压缩率能有 50%,也就是说 100K 的数据能够压缩成 50K 的大小,那么就相当于在带宽不变的情况下网速提升了一倍,加速的效果是非常明显的

  • 缺点

    gzip 等压缩算法通常 只对文本文件有较好的压缩率,而图片、音频视频等多媒体数据本身就已经是高度压缩的,再用 gzip 处理也不会变小,所以它就失效了

2/4、分块传输 chunked

  • 标志:响应头 Transfer-Encoding: chunked,意思是报文里的 body 部分不是一次性发过来的,而是分成了许多的块(chunk)逐个发送

  • 分块传输的编码规则:

    1、每个分块包含两个部分,长度头数据块

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

    3、数据块紧跟在长度头后,最后也用 CRLF 结尾,但数据不包含 CRLF

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

    image-20210425203723581

    image-20210425203804447

范围请求

客户端在 请求头 里使用 Range:bytes=x-y 来表示只获取文件的一部分;

  • 注意:范围请求不是 Web 服务器必备的功能,服务器在 响应头 中需要通过Accept-Ranges: bytes来声明是支持范围请求的

请求头 中的字段 Range 支持很多种格式写法:

  • x 和 y 是以 字节 为单位的数据范围,起点 x 和终点 y 可以省略,能够很方便地表示正数或者倒数的范围

    1、0- 表示从 文档起点到文档终点,相当于 0-99,即整个文件

    2、10- 是从第 10 个字节开始到文档末尾,相当于 10-99

    3、-1 是文档的最后一个字节,相当于 99-99

    4、-10是从文档末尾倒数 10 个字节,相当于 90-99

服务器收到请求头中的 Range 字段,需要进行几步操作:

1、检查范围是否合法 - 范围有误则返回状态码 - 416

2、根据 Range 头计算偏移量,读取文件的片段 - 206 Partial Content,表示 body 只是原数据的一部分

3、服务器要添加一个 响应头 字段 Content-Range,表示片段的实际偏移量和资源的总大小,格式是 bytes x-y/length(与 Range 头区别在没有 =,范围后多了总长度)

4、发送数据 - 把片段用 TCP 发给客户端

多段数据

请求头 Range 头里使用多个 x-y,一次性获取多个片段数据

响应头形式如下,可以结合图片理解:

  • 用一个参数 boundary=xxx 给出段之间的分隔标记

1、每一个分段必须以 --boundary 开始

2、之后要用 Content-Type:multipart/byterangesContent-Range 标记这段数据的类型是多段字节序列组成和所在范围

3、以回车换行结束,再加上分段数据

4、最后用一个 --boundary-- 表示所有的分段结束

image-20210425204018340image-20210425204052500