略微加速

略速 - 互联网笔记

HTTP静态文件续传ETag/Range

2021-02-07 leiting (1912阅读)

标签 网络 HTTP

HTTP 标准ETAG方案:

使用HTTP 的ETAG来标识是否文件已经修改。

ETAG原理:如果URL上的资源内容改变,一个新的不一样的ETag就会被分配。用这种方法使用ETag即类似于指纹,并且他们能够被快速地被比较,以确定两个版本的资源是否相同。ETag的比较只对同一个URL有意义——不同URL上的资源的ETag值可能相同也可能不同,从他们的ETag的比较中无从推断。

ETAG是HTTP的一个可选字段,且没有规范他的实现;实际上业内用的比较多的就是使用MD5签名的方式来生成(linux shell md5sum)

典型用法:

server端: Nginx >1.3.3 自带有ETAG的module , 当然同时也可以在业务代码里SetHeaders加一个ETAG字段

client端:

第一次请求时:

String etag = httpURLConnection.getHeaderField("ETag");

ETag: "b428eab9654aa7c87091e"

第二次请求(断点续传时):

httpURLConnection.setRequestProperty(“If-None-Match”, "b428eab9654aa7c87091e"); 

If-None-Match: "b428eab9654aa7c87091e"

如果ETag值匹配,这就意味着资源没有改变,服务器便会发送回一个极短的响应,包含HTTP “304 未修改”的状态。304状态告诉客户端,它的缓存版本是最新的,并应该使用它。

然而,如果ETag的值不匹配,这就意味着资源很可能发生了变化,那么,一个完整的响应就会被返回,包括资源的内容,就好像ETag没有被使用。这种情况下,客户端可以用新返回的资源和新的ETag替代先前的缓存版本。

 

续传支持:

对于一个C/C++程序员,第一时间会得出一个系统级实现方案:

1. 客户端传当前的offset

2. server端seek到文件特定的offset开始读取往http connection吐数据

不过我们深处在一个开放方案和标准不断完善的时代,不需要自己实现一个(这也是像我这样的C/C++研发工程师越来越没落的原因),来看看HTTP协议是怎么解决这个问题的:

HTTP头Range字段:

Range : 用于客户端到服务器端的请求,可通过该字段指定下载文件的某一段大小,及其单位。典型的格式如: 

Range: bytes=0-499 下载第0-499字节范围的内容
Range: bytes=500-999 下载第500-999字节范围的内容
Range: bytes=-500 下载最后500字节的内容
Range: bytes=500- 下载从第500字节开始到文件结束部分的内容

来个简单粗暴的例子

curl --header "Range: bytes=0-20000" xxx.com/memcache.pdf -o part1
curl --header "Range: bytes=20001-223651" xxx.com/memcache.pdf -o part2
cat part1 part2 >> a.pdf


北京半月雨文化科技有限公司.版权所有 京ICP备12026184号-3