一、断点续传原理
HTTP协议规定了如何传输某个资源的一部分,而不是全部。比如,有一个文件的大小是1000字节,浏览器可以只请求该文件的前300个字节,或者只请求第500到第1000个字节。通过这种方式,就可以不必在一次请求中传输某个资源的全部内容,而是发起多次请求,每次仅请求其中的一部分内容。等所有这些请求都返回之后,再把得到的内容一块一块的拼接起来得到完整的资源。
实现断点续传,利用HTTP协议的上述特性。
当用户暂停下载的时候,浏览器会记录已经下载到什么位置,当用户在未来某一时间恢复下载时,就可以从上次暂停的位置继续下载,而不必从头开始。
二,断点续传实现方法
由于部分传输不是强制的,服务器可以支持也可以不支持,所以,需要在程序中告诉浏览器,它请求的资源是否支持部分传输。
这可以通过设置HTTP的 Accept-Ranges 响应头信息来实现。
PHP代码:
Accept-Ranges: bytes 告诉浏览器,该资源支持以字节为单位的部分传输。这个响应头需要附加在支持部分传输的所有资源上。
当接受到一个请求时,需要从浏览器的请求中提取浏览器具体是在请求资源的哪一个部分。这个信息是通过 Range 请求头来传递的。
在PHP中,它被存储在$_SERVER['HTTP_RANGE']中。我们需要检查这个变量是否定义了,如果定义了,则使用该值,否则,就将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响应头信息,具体如下:
例子:
这里的$length需要注意一下,它的取值是本次传输的内容的长度,而不是整个文件的长度。另外需要注意的一点是,这里的HTTP状态码是206,不是200。
编后语:
文件下载的断点续传实际上是利用了HTTP协议中对传输部分文件的支持。而HTTP协议的这一特性不仅可以用于实现断点续传,客户端程序也可以利用它来实现多线程下载。
在实现断点续传的过程中,需要注意正确设置各种HTTP头信息。错误的头信息将导致用户下载到的文件损坏,无法使用。