教程集 www.jiaochengji.com
教程集 >  脚本编程  >  php  >  正文 PHP支持断点续传的下载代码

PHP支持断点续传的下载代码

发布时间:2017-11-09   编辑:jiaochengji.com
如何让php支付断点续传的文件下载呢?这里详细介绍下php下载文件时断点续传的实现方法,有需要的朋友做个参考吧。

让PHP下载代码支持断点续传 主要靠的 HTTP协议中header Content-Range来实现。

一,HTTP的下载原理
对于HTTP协议,向服务器请求某个文件时,只要发送类似如下的请求即可:
GET /Path/FileName HTTP/1.0
Host: www.server.com:80
Accept: **表示接收任何类型的数据。User-Agent表示用户代理,这个字段可有可无,但强烈建议加上,因为它是服务器统计、追踪以及识别客户端的依据。Connection字段中的close表示使用非持久连接。

关于HTTP协议更多的细节可以参考RFC2616(HTTP 1.1)。
如果服务器成功收到该请求,并且没有出现任何错误,则会返回类似下面的数据:
HTTP/1.0 200 OK
Content-Length: 13057672
Content-Type: application/octet-stream
Last-Modified: Wed, 10 Oct 2005 00:56:34 GMT
Accept-Ranges: bytes
ETag: "2f38a6cac7cec51:160c"
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Date: Wed, 16 Nov 2005 01:57:54 GMT
Connection: close

这些返回信息的含义。

第一行是协议名称及版本号,空格后面会有一个三位数的数字,是HTTP协议的响应状态码,200表示成功,OK是对状态码的简短文字描述。状态码共有5类:
1xx属于通知类;
2xx属于成功类;
3xx属于重定向类;
4xx属于客户端错误类;
5xx属于服务端错误类。

对 于状态码,相信大家对404应该很熟悉,如果向一个服务器请求一个不存在的文件,就会得到该错误,通常浏览器也会显示类似“HTTP 404 – 未找到文件”这样的错误。Content-Length字段是一个比较重要的字段,它标明了服务器返回数据的长度,这个长度是不包含HTTP头长度的。换句话说,我们的请求中并没有Range字段(后面会说到),表示我们请求的是整个文件,所以Content-Length就是整个文件的大小。其余各字段是一些关于文件和服务器的属性信息。
以上就是通过HTTP协议实现文件下载的全过程。但还不能实现断点续传,而实际上断点续传的实现非常简单,只要在请求中加一个Range字段就可以了。
假如一个文件有1000个字节,那么其范围就是0-999,则:
Range: bytes=500- 表示读取该文件的500-999字节,共500字节。
Range: bytes=500-599 表示读取该文件的500-599字节,共100字节。
Range还有其它几种写法,但上面这两种是最常用的,对于断点续传也足矣了。如果HTTP请求中包含Range字段,那么服务器会返回206(Partial Content),同时HTTP头中也会有一个相应的Content-Range字段,类似下面的格式:
Content-Range: bytes 500-999/1000
Content-Range字段说明服务器返回了文件的某个范围及文件的总长度。这时Content-Length字段就不是整个文件的大小了,而是对应文件这个范围的字节数,这一点一定要注意。

PHP对断点续传支持的演示:
先定义一个函数 getRange() 这个函数用来处理 header中 Range 具体数据的处理
 

复制代码 代码示例:
<?php
/** $file_size  文件大小 */
 function getRange($file_size){
    $range = isset($_SERVER['HTTP_RANGE'])?$_SERVER['HTTP_RANGE']:null;
    if(!empty($range)){
        $range = preg_replace('/[\s|,].*/', '', $range);
        $range = explode('-',substr($range,6));
        if (count($range) < 2 ) {
            $range[1] = $file_size;
        }
        $range = array_combine(array('start','end'),$range);
        if (empty($range['start'])) {
            $range['start'] = 0;
        }
        if (!isset ($range['end']) || empty($range['end'])) {
            $range['end'] = $file_size;
        }
        return $range;
    }
    return null;
}

假设文件的地址为 $file_path,代码:
 

复制代码 代码示例:
<?php
$speed = 512;//此参数为下载最大速度
$pos = strrpos($file_path, "/");
$file_name = substr($file_path, $pos+1);
$file_size = filesize($file_path);
$ranges = getRange($file_size);
$fh =  fopen($file_path, "rb");
header('Cache-control: public');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.$file_name);
if ($ranges != null) {
    header('HTTP/1.1 206 Partial Content');
    header('Accept-Ranges: bytes');
    header(sprintf('Content-Length: %u',$ranges['end'] - $ranges['start']));
    header(sprintf('Content-Range: bytes %s-%s/%s', $ranges['start'], $ranges['end'], $file_size));
    fseek($fh, sprintf('%u',$ranges['start']));
}else{
    header("HTTP/1.1 200 OK");
    header(sprintf('Content-Length: %s', $file_size));
} // www.jbxue.com
while(!feof($fh))
{
    echo  fread($fh, round($speed*1024, 0));
    ob_flush();
    sleep(1);
}
($fh != null) && fclose($fh);
 

基本如此,即可解决一般性文件的断点续传或下载。

您可能感兴趣的文章:
php下载远程文件的类(支持断点续传)
php 断点续传的简单例子
php断点续传下载示例代码
php超大文件下载及断点续传下载的实现代码
php大文件下载代码(支持断点续传)
php支持断点续传的文件下载类(附源码)
PHP支持断点续传的下载代码
PHP 中使用 TUS 协议来实现大文件的断点续传
.Net/C#: 实现支持断点续传多线程下载的 Http Web 客户端工具类 (C# DIY Ht
php下载远程文件的类(断点续传)实例分享

关键词: PHP文件下载  断点续传   
[关闭]
~ ~