WOW暴雪下载器python断点续传下载器时多出个文件

前几天一个同事跑过来找我说,我们在广告素材视频这块想做断点续传,就是这次某个视频缓存到一半,下次不用重头开始,可以在原来停留得位置开始继续下载.以提供更好的用户体验。
同时说需要我们支持吐素材地址的业务接口告诉终端最后修改时间/文件签名(md5),用这个用来判断我当前要下的文件有没有变化,同时告诉终端文件的Size大小.
我一细想,这个问题压根不需要通过改变现有接口提供更多的数据来做.下面从原理实现上简单说下:
对于断点续传,关键点是两个:
1. 终端知道当前的文件和上一次加载的文件是不是内容发生了变化,如果有变化,需要重新从offset 0 的位置开始下载
2. 终端记录好上次成功下载到的offset,告诉server端,server端支持从特定的offset 开始吐数据
文件变化感知:
前置业务接口方案:
对于关键点1,对于决定大部分产品的业务场景,可以通过前置业务接口解决;这里简单介绍一下:
对于非下载工具类的产品,如视频APP(奇艺,优酷),视频播放前会请求相关业务的信息,主要返回片子叫什么名字,主要演员等等一些列信息,同时会返回一个对于播放最重要的信息&&播放地址。&
播放地址就是我们可以做文章的地方,如果《太子妃第一集》这个片子更新了(被广电要求减掉某个污的画面),可以后端系统让这个业务接口吐不同的播放地址/一个不同的url参数(?ver=1.1)/位置参数(#ver1.1)。这样纯天然的URL变化能纯天然的让终端认为不是同一个片子,而需要重新加载。
HTPP 标准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: "b428eab91e"
第二次请求(断点续传时):
httpURLConnection.setRequestProperty(&If-None-Match&, "b428eab91e");&
If-None-Match: "b428eab91e"
如果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" /memcache.pdf -o part1curl --header "Range: bytes=" /memcache.pdf -o part2cat part1 part2 && a.pdf
衍生阅读:
阅读(...) 评论()PHP实现文件下载断点续传详解
投稿:junjie
字体:[ ] 类型:转载 时间:
这篇文章主要介绍了PHP实现文件下载断点续传详解,本文讲解了载断点续传的实现理解,并给出了实现代码,需要的朋友可以参考下
如果我们的网站提供文件下载的服务,那么通常我们都希望下载可以断点续传(Resumable Download),也就是说用户可以暂停下载,并在未来的某个时间从暂停处继续下载,而不必重新下载整个文件。
通常情况下,Web服务器(如Apache)会默认开启对断点续传的支持。因此,如果直接通过Web服务器来提供文件的下载,可以不必做特别的配置,即可享受到断点续传的好处。由于这些文件直接通过Web服务器来提供下载,后端脚本无法对这个下载过程进行控制。这对于仅提供公开、静态文件的网站来说不是问题,但对于需要提供私有、动态文件的网站来说,直接通过Web服务器来提供下载就无法满足需求了。这时,就需要在编写后台脚本程序时,加入对断点续传的支持。
本文将以PHP为例,简要介绍实现文件下载断点续传的方法。
断点续传的原理还是比较直观的。
HTTP协议规定了如何传输某个资源的一部分,而不是全部。比如,有一个文件的大小是1000字节,浏览器可以只请求该文件的前300个字节,或者只请求第500到第1000个字节。通过这种方式,就可以不必在一次请求中传输某个资源的全部内容,而是发起多次请求,每次仅请求其中的一部分内容。等所有这些请求都返回之后,再把得到的内容一块一块的拼接起来得到完整的资源。
实现断点续传就是要利用HTTP协议的上述特性。当用户暂停下载的时候,浏览器会记录已经下载到什么位置,当用户在未来某一时间恢复下载时,就可以从上次暂停的位置继续下载,而不必从头开始。
由于部分传输不是强制的,服务器可以支持也可以不支持,所以,我们需要在程序中告诉浏览器,它请求的资源是否支持部分传输。这可以通过设置HTTP的 Accept-Ranges 响应头信息来实现。PHP代码如下:
header('Accept-Ranges: bytes');
Accept-Ranges: bytes 告诉浏览器,该资源支持以字节为单位的部分传输。这个响应头需要附加在支持部分传输的所有资源上。
当接受到一个请求时,我们需要从浏览器的请求中提取浏览器具体是在请求资源的哪一个部分。这个信息是通过 Range 请求头来传递的。在PHP中,它被存储在$_SERVER['HTTP_RANGE']中。我们需要检查这个变量是否定义了,如果定义了,则使用该值,否则,就将range设为整个资源。
$range = "0-". ($content_length-1);
if(isset($_SERVER['HTTP_RANGE'])){
&&& $range = $_SERVER['HTTP_RANGE'];
接下来,就需要分析 $range 的值,来决定返回资源的哪一部分内容。可能的取值示例:
100-200 // 第100到第200字节
500-&&& // 第500字节到文件末尾
-1000&& // 最后的1000个字节
这里需要注意,得到一个Range之后,你需要对它的取值进行检验,包括:
1.开始位置非负
2.结束位置需要大于开始位置
3.开始位置需要小于文件长度减一 (因为这里的位置索引是从0开始的)
4.若结束位置大于文件长度减一,则需要把它的值设置为文件长度减一
如果Range的取值不合法,则需要终止程序并告知浏览器:
header('HTTP/1.1 416 Requested Range Not Satisfiable');
为了保持文章简洁,具体的校验代码这里就不提供了。下面假定你已经校验了Range的取值,并得到了 $start 和 $end 两个变量,分别表示开始位置和结束位置。
接下来要做的就是把文件的对应部分的内容发送给浏览器。不过要注意的是,这里涉及到需要发送多个HTTP响应头信息,具体如下:
header('HTTP/1.1 206 Partial Content');
header('Accept-Ranges: bytes');
header("Content-Range: bytes $start-$end/$filesize");
$length = $end - $start + 1;
header("Content-Length: $length");
/* 输出文件的指定部分 */
这里的$length需要注意一下,它的取值是本次传输的内容的长度,而不是整个文件的长度。另外需要注意的一点是,这里的HTTP状态码是206,不是200。
文件下载的断点续传实际上是利用了HTTP协议中对传输部分文件的支持。而HTTP协议的这一特性不仅可以用于实现断点续传,客户端程序也可以利用它来实现多线程下载。
在实现断点续传的过程中,需要注意正确设置各种HTTP头信息。错误的头信息将导致用户下载到的文件损坏,无法使用。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具

参考资料

 

随机推荐