咸鱼

咸鱼是以盐腌渍后,晒干的鱼

0%

深入解析HTTP--断点续传

断点下载HTTP协议中有支持,一般的Web服务器都会支持,如 nginx

HTTP 协议范围请求允许服务器只发送 HTTP 消息的一部分到客户端。范围请求在传送大的媒体文件,或者与文件下载的断点续传功能搭配使用时非常有用。

应用场景

  • 断点下载,下载大文件可以暂停。
  • 多任务/多线程下载大文件(类似迅雷软件)

一、检查服务器是否支持断点续传

1
2
3
4
5
6
7
8
9
10
11
12
13
root@bogon:~# curl -I http://192.168.0.30/test.txt
HTTP/1.1 200 OK
Server: nginx
Date: Fri, 16 Aug 2019 02:00:07 GMT
Content-Type: text/plain
Content-Length: 6000
Last-Modified: Tue, 13 Aug 2019 09:45:45 GMT
Connection: keep-alive
ETag: "5d5286c9-1770"
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: *
Access-Control-Allow-Credentials: true
Accept-Ranges: bytes
  • 响应中 Accept-Ranges: bytes 字段表示支持断点续传,并且单位是 bytes
  • 响应中 Content-Length: 6000 是文件的完整大小。

如果服务器响应未发送 Accept-Ranges ,那么它们有可能不支持断点续传。一些服务器会明确将其值设置为 “none”,以此来表明不支持。在这种情况下,某些应用的下载管理器会将暂停按钮禁用。

二、请求特定的范围

假如服务器支持 Range 请求的话,你可以在 Header 中 使用 Range 指示服务器应该返回文件的某部分。

单一范围

只需在 Headers 中加入 Range 字段,如

1
Range: "bytes=0-99"

表示请求文件的前100个字节,服务器端会返回状态码为 HTTP/1.1 206 Partial Content 的响应

curl请求如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
root@bogon:~# curl http://192.168.0.30/test.txt -i -H "Range: bytes=0-99"
HTTP/1.1 206 Partial Content
Server: nginx
Date: Fri, 16 Aug 2019 02:10:05 GMT
Content-Type: text/plain
Content-Length: 100
Last-Modified: Tue, 13 Aug 2019 09:45:45 GMT
Connection: keep-alive
ETag: "5d5286c9-1770"
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: *
Access-Control-Allow-Credentials: true
Content-Range: bytes 0-99/6000

1ababadalgharaghtakamminarronnkonnbronntonnerronntbababadalgharaghtakamminarronnkonnbronntonnerronnt

多重范围

Range头部也支持一次请求文档的多个部分。请求范围用一个逗号分隔开。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
root@bogon:~# curl http://192.168.0.30/test.txt -i -H "Range: bytes=0-50, 100-150"
HTTP/1.1 206 Partial Content
Server: nginx
Date: Fri, 16 Aug 2019 02:12:14 GMT
Content-Type: multipart/byteranges; boundary=00000000029
Content-Length: 278
Last-Modified: Tue, 13 Aug 2019 09:45:45 GMT
Connection: keep-alive
ETag: "5d5286c9-1770"
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: *
Access-Control-Allow-Credentials: true


--00000000029
Content-Type: text/plain
Content-Range: bytes 0-50/6000

1ababadalgharaghtakamminarronnkonnbronntonnerronntb
--00000000029
Content-Type: text/plain
Content-Range: bytes 100-150/6000

2ababadalgharaghtakamminarronnkonnbronntonnerronntb
--00000000029--

Content-Type:multipart/byteranges 表示这个响应有多个 byterange 。每一部分 byterange 都有他自己的 Content-Type 头部和 Content-Range ,并且使用 boundary 参数对body进行划分。

条件式范围请求

当(中断之后)重新开始请求更多资源片段的时候,必须确保自从上一个片段被接收之后该资源没有进行过修改。

The If-Range 请求首部可以用来生成条件式范围请求:
假如条件满足的话,条件请求就会生效,服务器会返回状态码为 206 Partial 的响应,以及相应的消息主体。
假如条件未能得到满足,那么就会返回状态码为 200 OK 的响应,同时返回整个资源。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
root@bogon:~# curl http://192.168.0.30/test.txt -i -H "Range: bytes=100-120" -H "If-Range: Tue, 13 Aug 2019 09:45:45 GMT"
HTTP/1.1 206 Partial Content
Server: nginx
Date: Fri, 16 Aug 2019 02:27:22 GMT
Content-Type: text/plain
Content-Length: 21
Last-Modified: Tue, 13 Aug 2019 09:45:45 GMT
Connection: keep-alive
ETag: "5d5286c9-1770"
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: *
Access-Control-Allow-Credentials: true
Content-Range: bytes 100-120/6000

2ababadalgharaghtakam