Http系列:断点续传与多线程下载

2020-10-26  本文已影响0人  前端三少爷

前言

当下载电影时,我常常会想中断下载后,为什么点击开始时会在中断的地方继续下载呢?
又或者在看在线电影时,为什么可以按着播放条拖动就能看到想看的片段呢?

http的range请求将解决以上困惑。

多线程、断点续传、随机点播等的场景的步骤

1、客户端明确任务:从哪开始下载

2、下载文件的指定部分内容
3、下载完毕后拼装成统一的文件

HTTP Range规范

在RFC7233中有详细介绍
1、允许服务器基于客户端的请求只发送响应包体的一部分给到客户端,而客户端自动将多个片段的包体组合成完整的体积更大的包体。

2、服务器通过Accept-Range头部表示是否支持Range请求

Range请求范围的单位

基于字节为单位的时候,举例:设置响应体长度为10000

通过Range头部传递请求范围,如:Range: bytes=0-499

测试

下面用一些小例子有测试一下。
用node搭了一个简单的服务器,返回的数字是22个字节的响应体

'Hello World 0123456789';
现在用curl命令获取全部的响应体,然后访问0-5的字节段: 图一

-H参数添加 HTTP 请求的标头。
上面的命令就是添加HTTP头Range: bytes=0-5。
返回的是Hello (加上空格)一共六个字节。

现在获取第21个字节及以后的字节段,就可以用20-: 图二

返回的是89

Range条件请求

测试

下面用etag测试一下Range条件请求

首先获取0-5字节段


图三

然后用-I来看看生成Hello 时服务器生成Etag的值


图四

接下来,用这个值放到If-Match中获取6-10字节段:World


图五

如果Etag发生了变化,来看看结果会怎么样,将最后的0改为1


图六

返回412 Precondition Failed

结论

通过条件请求可以判断两次下载之间,服务器端资源有没有发生变化。如果发生了变化,就可以通过412这个响应知道,资源已经发生了变化。

服务器响应

如果只获取部分的body,那么服务器端返回的响应码不是200,而是206。
206 Partial Content

测试

用一个视频播放的例子来看看206响应的样子。


图六

416 Range Not Statisfiable

测试

如果获取范围超出实际资源的大小,比如获取30-40。返回416


图七

200 OK

多重范围与multipart

测试

获取5-10, 10-15片段。


图八

总结

1、客户端通过Range头部传递请求范围

2、服务端返回Accept-Range头部表示是否支持Range请求。

3、客户端如果在得到Range响应的一部分,并想在这部分响应未过期的情况下,获取其他部分的响应,可以用If-Range头部使用Etag或者Last-Modified为值。

4、只获取部分的body,服务器返回206响应码,其中Content-Range头部显示当前片段响应体在完整包体中的位置

5、客户端想多重范围下载资源,在Range头部的格式为Range: bytes=0-50, 100-150...(用逗号分隔)
响应头部Content-Type: multipart/byteranges; boundary=...

作者: zhangwinwin
链接:Http系列:断点续传与多线程下载
来源:github

上一篇 下一篇

猜你喜欢

热点阅读