关于大文件传输你要了解的 HTTP 知识

3,178 阅读4分钟

我正在参加「掘金·启航计划」

当页面请求大文件时,几百 M 的文件肯定不可能一口气传输过来。 那需要长时间的等待,非常影响用户体验。

肯定是需要分段传输~

那么,它到底是怎么传输过来的呢?


首先,他要两方的支持

受请求方——服务器的支持

在 HTTP 响应头字段中加上

Accept-Ranges: bytes

Accept-Ranges

Accept-Ranges接受两种参数

none

不支持任何范围请求单位,由于其等同于没有返回此头部,因此很少使用。不过一些浏览器,比如 IE9,会依据该头部去禁用或者移除下载管理器的暂停按钮。

bytes

范围请求的单位是 bytes(字节)。

就是要设置为 bytes 来通知发送请求方——客户端,这里支持范围请求,支持的范围单位是 bytes

请求方——客户端的支持

服务端是同意了,但它要怎么知道你想请求的范围 是哪一块呢?

就要靠 HTTP 请求头中的 Range 字段

Range

The Range 是一个请求首部,告知服务器返回文件的哪一部分。在一个 Range 首部中,可以一次性请求多个部分,服务器会以 multipart 文件的形式将其返回。如果服务器返回的是范围响应,需要使用 206 Partial Content 状态码。假如所请求的范围不合法,那么服务器会返回 416 Range Not Satisfiable 状态码,表示客户端错误。服务器允许忽略 Range 首部,从而返回整个文件,状态码用 200

语法

<unit>=<range-start>-<range-end>

Range: bytes=200-1000, 19000-

表示 第 200 到 1000 个字节 + 第19000 个字节到最后

是的,除了请求一段也可以多段数据


响应

  • 范围不合法:返回 416
  • 服务器忽略 Range 首部: 返回 200
  • 成功: 206

If-Range

If-Range HTTP 请求头字段用来使得 Range 头字段在一定条件下起作用:当字段值中的条件得到满足时,Range 头字段才会起作用,同时服务器回复206 部分内容状态码,以及Range 头字段请求的相应部分;如果字段值中的条件没有得到满足,服务器将会返回 200 OK 状态码,并返回完整的请求资源。

字段值中既可以用 Last-Modified 时间值用作验证,也可以用ETag标记作为验证,但不能将两者同时使用。

If-Range 头字段通常用于断点续传的下载过程中,用来自从上次中断后,确保下载的资源没有发生改变。

If-Range 就等于是 在 Range 前的一个 if 语句, 条件满足了,true 了才进入其中

单段 & 多段数据

前面提到了请求数据时有分请求单段和多段数据,两者有什么区别呢?

单段

如果只是单段,那就很简单

这里以 b站 一个视频的请求作为例子

请求头

这里只截取本文相关的部分

if-range: Thu, 29 Sep 2022 00:46:42 GMT
range: bytes=279550-919231

响应头

HTTP/1.1 206 Partial Content
accept-ranges: bytes
Content-Length: 639682
Content-Range: bytes 279550-919231/103452930
content-type: video/mp4

可以看到 响应头 Content-Range 前半部分 279550-919231和请求头中的 range 是相对应的,Content-Length 也正是他们相减加一。

Content-Range /后半段的 103452930 则是资源的总大小

多段数据

多端数据的相应则大概是这样的:

HTTP/1.1 206 Partial Content
Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT
Content-Length: 1741
Content-Type: multipart/byteranges; boundary=BOUNDARY

--BOUNDARY
Content-Type: application/pdf
Content-Range: bytes 500-999/8000

...the first range...
--BOUNDARY
Content-Type: application/pdf
Content-Range: bytes 7000-7999/8000

...the second range
--BOUNDARY--

与上面的单个字段的响应头相比,很明显的不同之处就在于 Content-Type字段

该字段由分号;分为两部分

第一部分是:multipart/byteranges,表示请求是多段数据请求

第二部分是:boundary=BOUNDARY,响应体中的分隔符是BOUNDARY—— 在后续的内容中也可以看出来,每一段由一个--BOUNDARY表示分隔

并且在最后的一个boundary的末尾还会有--代表多段数据传输的结束。

总结

本文从接受请求方& 发起请求方的支持说起,后面再提到相关的各种头部字段,希望大家能对 HTTP 有更深入的理解~

参考

文中措辞、知识点、格式如有疑问或建议,欢迎评论~你对我很重要~
🌊如果有所帮助,欢迎点赞关注,一起进步⛵这对我很重要~