/xia栽ke:52xueit.com/590/
在某次摸鱼的过程中,老大突然后面冒出来说要做一个拉取文件到本地的需求(写的时候疯狂回头🤡),当时心想这简单,不就一个HttpClient或者RestTemplate的事情嘛,很快一两天就给整出来心满意足的提交了。
不出意外的话要出意外了,老大看了一眼我的代码就问:“你没有做断点续传吗”,我:“啊?”(好吧得加班了)
因为当时我还没有玩过断点续传,老大就和我提了一嘴可以考虑使用Range请求头来实现,在我巴拉巴拉的有一两天后,最终断点续传版本的网络文件下载功能就出来了(工具类加一✔)
省流:本文章除了断点续传的视线,还发散介绍了Range请求头和一些零零散散的其他小东西,不感兴趣的小伙伴可直接跳至“断点续传下载实现”。
1、Range请求头
1.1、概述
顾名思义,HTTP/1.1 Range请求头代表发送范围获取数据的请求,要求服务器仅向客户端回传HTTP消息的一部分,格式以及示例如下:
shell复制代码Range: <数据格式>=<数据开始的索引位置>-<数据结束的索引位置> # 1. 请求从0至500的byte数据: Range: bytes=0-500 # 2. 请求第500个byte以后的全部数据: Range: bytes=501- # 3. 请求最后500个byte的数据: Range:bytes=-500 # 4. 请求多个分段时,各分段以,分割: Range: bytes=0-100,101-200
1.2、使用限制
正是得益于Range请求头的这种特性,因此在很多断点续传的场景下都能看到它的身影,但在使用之前需要确定我们的请求中能否使用该请求头。
不知道大家伙有没有发现前面提及Range请求头的时候,我添加上了一个前缀“HTTP/1.1”,这是因为只在 HTTP/1.1(RFC2616) 之上,才支持范围请求。所以如果客户端或者服务端两端的某一端低于 HTTP/1.1,我们就不应该使用范围请求的功能。我们可以通过 curl -i命令来测试一下是否支持范围请求:
如果 HTTP 响应中存在 Accept-Ranges 标头,并且其值不是 none,那么该服务器支持范围请求。
1.3、范围请求
当我们确定可以使用范围请求后,我们便可愉快的开始发起请求啦。这里以获取前1024bytes数据为例:Range 还有几种不同的方式来限定范围,可以根据需要灵活定制:
500-1000:指定开始和结束的范围,一般用于多线程分片下载。
500-:指定开始区间,一直传递到结束。这个就比较适用于断点续传、或者在线播放等等。
-500:无开始区间,只意思是需要最后 500 bytes 的内容实体。
100-300,1000-3000:指定多个范围,这种方式使用的场景很少,了解一下就好了。
在响应中我们可以很明确看到206响应码和Content-Range范围响应数据:
HTTP 206 Partial Content 成功状态响应代码表示请求已成功,进一步了解可查看206 Partial Content - HTTP | MDN
Content-Range标记当前传递的内容实体范围和总长度,单位是bytes
1.4、预防资源变更
我们在网上偶尔也会发现一个现象:下载大尺寸资源的时候,偶尔中间暂停过再重新下载,资源又重头开始了下载。这看似断点续传功能失效了,但实际上并不一定,可能是在这期间该资源发生了变更。
针对以上情况,可以使用If-Range请求头标记创建具有条件的范围请求,条件没有得到满足,服务器将返回完整的资源以及 200 OK 状态。