❕大文件传输
数据压缩:默认开启,通常是保底的。详见内容协商
request
Accept-Encoding
headerresponse
Content-Encoding
header
分块传输:response 化整为零
范围请求:request 化整为零。可以仅一个范围,也可以多个范围
以上四种方式不是互斥的,可以混合起来使用。
分块传输
一个 response 报文的 body 总长度,要么已知 Content-Length
,要么未知 chunked
。
# 报文里的 body 不是一次性全发过来,而是分成了许多的 chunks 块逐个发送
Transfer-Encoding: chunked
分块传输时 body 的编码规则:length 和 chunked data,如下:
每个 chunk 包含两个部分:length 是 16 进制的数字,data 紧跟在 length 之后,最后也以 CRLF 结尾,但数据不包含 CRLF。
最后用一个 length 为 0 的 chunk 表示结束,即 0\r\n\r\n
。其中,第一个 \r\n
表示 CRLF(回车换行),第二个 \r\n
表示正常 HTTP 报文中 header 和 body 的分隔空行。
需要说明的是,浏览器在收到分块传输的数据后,会自动按照规则去掉分块编码,重新组装好内容。若想看 server 发出的分块的原始报文形态,要用 Wireshark 抓包,或用 Telnet 手工发送请求。
范围请求
范围请求,range request,可以只获取部分数据,从而实现视频拖拽、断点续传、多段下载等。可以一次只请求一个范围,也可以一次请求“多个”范围。
范围请求,允许客户端在请求 header 里使用专用字段 Range
来表示只想获取文件的一部分。
Range: bytes=x-y
206 Partial Content
Content-Range: bytes x-y/length
Range: bytes=x-y, x1-y1
Content-Type: multipart/byteranges; boundary=xx
Range
Range
格式是 bytes=x-y
,其中 x 和 y 是以字节为单位的数据偏移量,且都可以省略。
# request
Range: bytes=0-9 # 前 10 个字节
Range: bytes=10-19 # 第二个 10 字节
Range: bytes=0-10 # 前 11 个字节
Range: bytes=0- # 从文档起点到文档终点,即整个文件
Range: bytes=10- # 从第 10 个字节开始到文档末尾
Range: bytes=-1 # 文档的最后一个字节
Range: bytes=-10 # 从文档末尾倒数 10 个字节
在服务器收到 Range 字段后:
检查范围是否合法。若越界了,会返回状态码
416
如果范围正确,便根据 Range 计算偏移量,读取文件的片段
206 Partial Content
状态码Content-Range
header 告诉片段的实际偏移量和资源总大小,格式是bytes x-y/length
发送数据,把片段用 TCP 发给客户端
# request
GET / HTTP/1.1
Host: www.xxx.com
Range: bytes=0-31
# response
HTTP/1.1 206 Partial Content
Content-Length: 32
Accept-Ranges: bytes
Content-Range: bytes 0-31/96
This is a plain text json doc.
多个范围
# response
Content-Type: multipart/byteranges; boundary=xx
MIME 类型
multipart/byteranges
,表示报文的 body 是由多段字节序列组成的参数
boundary
给出段之间的分隔标记
多段数据的格式,如下:
每个分段必须以
--boundary
开始之后用
Content-Type
和Content-Range
标记这段数据的类型和所在范围最后用一个
--boundary--
表示所有的分段结束
# request
GET / HTTP/1.1
Host: www.xxx.com
Range: bytes=0-9, 20-29
# response
HTTP/1.1 206 Partial Content
Content-Type: multipart/byteranges; boundary=00000000001
Content-Length: 189
Connection: keep-alive
Accept-Ranges: bytes
--00000000001
Content-Type: text/plain
Content-Range: bytes 0-9/96
// this is
--00000000001
Content-Type: text/plain
Content-Range: bytes 20-29/96
ext json d
--00000000001--
这时响应报文的 body 里的多个部分会用 boundary
字符串 00000000001
分隔。
Last updated