设为首页 收藏本站
查看: 478|回复: 0

[经验分享] php 支持断点续传的文件下载类

[复制链接]

尚未签到

发表于 2015-8-26 14:43:08 | 显示全部楼层 |阅读模式
php 支持断点续传的文件下载类

分类: php class2013-06-30 17:27 17748人阅读 评论(6) 收藏 举报
php断点续传下载http测试
php 支持断点续传,主要依靠HTTP协议中 header HTTP_RANGE实现。
HTTP断点续传原理
Http头 Range、Content-Range()
HTTP头中一般断点下载时才用到Range和Content-Range实体头,
Range用户请求头中,指定第一个字节的位置和最后一个字节的位置,如(Range:200-300)
Content-Range用于响应头
请求下载整个文件:
GET /test.rar HTTP/1.1
Connection: close
Host: 116.1.219.219
Range: bytes=0-801 //一般请求下载整个文件是bytes=0- 或不用这个头
一般正常回应
HTTP/1.1 200 OK
Content-Length: 801      
Content-Type: application/octet-stream
Content-Range: bytes 0-800/801 //801:文件总大小
FileDownload.class.php



[php] view plaincopy

  • <?php
  • /** php下载类,支持断点续传
  • *   Date:   2013-06-30
  • *   Author: fdipzone
  • *   Ver:    1.0
  • *
  • *   Func:
  • *   download: 下载文件
  • *   setSpeed: 设置下载速度
  • *   getRange: 获取header中Range
  • */  

  • class FileDownload{ // class start  

  •     private $_speed = 512;   // 下载速度  


  •     /** 下载
  •     * @param String  $file   要下载的文件路径
  •     * @param String  $name   文件名称,为空则与下载的文件名称一样
  •     * @param boolean $reload 是否开启断点续传
  •     */  
  •     public function download($file, $name='', $reload=false){  
  •         if(file_exists($file)){  
  •             if($name==''){  
  •                 $name = basename($file);  
  •             }

  •             $fp = fopen($file, 'rb');  
  •             $file_size = filesize($file);  
  •             $ranges = $this->getRange($file_size);  

  •             header('cache-control:public');  
  •             header('content-type:application/octet-stream');  
  •             header('content-disposition:attachment; filename='.$name);  

  •             if($reload && $ranges!=null){ // 使用续传  
  •                 header('HTTP/1.1 206 Partial Content');  
  •                 header('Accept-Ranges:bytes');  

  •                 // 剩余长度  
  •                 header(sprintf('content-length:%u',$ranges['end']-$ranges['start']));  

  •                 // range信息  
  •                 header(sprintf('content-range:bytes %s-%s/%s', $ranges['start'], $ranges['end'], $file_size));  

  •                 // fp指针跳到断点位置  
  •                 fseek($fp, sprintf('%u', $ranges['start']));  
  •             }else{  
  •                 header('HTTP/1.1 200 OK');  
  •                 header('content-length:'.$file_size);  
  •             }

  •             while(!feof($fp)){  
  •                 echo fread($fp, round($this->_speed*1024,0));  
  •                 ob_flush();
  •                 //sleep(1); // 用于测试,减慢下载速度  
  •             }

  •             ($fp!=null) && fclose($fp);  

  •         }else{  
  •             return '';  
  •         }
  •     }


  •     /** 设置下载速度
  •     * @param int $speed
  •     */  
  •     public function setSpeed($speed){  
  •         if(is_numeric($speed) && $speed>16 && $speed<4096){  
  •             $this->_speed = $speed;  
  •         }
  •     }


  •     /** 获取header range信息
  •     * @param  int   $file_size 文件大小
  •     * @return Array
  •     */  
  •     private function getRange($file_size){  
  •         if(isset($_SERVER['HTTP_RANGE']) && !empty($_SERVER['HTTP_RANGE'])){  
  •             $range = $_SERVER['HTTP_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(empty($range['end'])){  
  •                 $range['end'] = $file_size;  
  •             }
  •             return $range;  
  •         }
  •         return null;  
  •     }

  • } // class end  

  • ?>
demo



[php] view plaincopy

  • <?php

  • require('FileDownload.class.php');  
  • $file = 'book.zip';  
  • $name = time().'.zip';  
  • $obj = new FileDownload();  
  • $flag = $obj->download($file, $name);  
  • //$flag = $obj->download($file, $name, true); // 断点续传  

  • if(!$flag){  
  •     echo 'file not exists';  
  • }

  • ?>
断点续传测试方法:
使用linux wget命令去测试下载, wget -c -O file http://xxx
1.先关闭断点续传
$flag = $obj->download($file, $name);



[plain] view plaincopy

  • fdipzone@ubuntu:~/Downloads$ wget -O test.rar http://demo.fdipzone.com/demo.php
  • --2013-06-30 16:52:44--  http://demo.fdipzone.com/demo.php
  • 正在解析主机 demo.fdipzone.com... 127.0.0.1
  • 正在连接 demo.fdipzone.com|127.0.0.1|:80... 已连接。
  • 已发出 HTTP 请求,正在等待回应... 200 OK
  • 长度: 10445120 (10.0M) [application/octet-stream]
  • 正在保存至: “test.rar”

  • 30% [============================>                                                                     ] 3,146,580    513K/s  估时 14s
  • ^C
  • fdipzone@ubuntu:~/Downloads$ wget -c -O test.rar http://demo.fdipzone.com/demo.php
  • --2013-06-30 16:52:57--  http://demo.fdipzone.com/demo.php
  • 正在解析主机 demo.fdipzone.com... 127.0.0.1
  • 正在连接 demo.fdipzone.com|127.0.0.1|:80... 已连接。
  • 已发出 HTTP 请求,正在等待回应... 200 OK
  • 长度: 10445120 (10.0M) [application/octet-stream]
  • 正在保存至: “test.rar”

  • 30% [============================>                                                                     ] 3,146,580    515K/s  估时 14s
  • ^C

  • 可以看到,wget -c不能断点续传

2.开启断点续传
$flag = $obj->download($file, $name, true);



[plain] view plaincopy

  • fdipzone@ubuntu:~/Downloads$ wget -O test.rar http://demo.fdipzone.com/demo.php
  • --2013-06-30 16:53:19--  http://demo.fdipzone.com/demo.php
  • 正在解析主机 demo.fdipzone.com... 127.0.0.1
  • 正在连接 demo.fdipzone.com|127.0.0.1|:80... 已连接。
  • 已发出 HTTP 请求,正在等待回应... 200 OK
  • 长度: 10445120 (10.0M) [application/octet-stream]
  • 正在保存至: “test.rar”

  • 20% [==================>                                                                               ] 2,097,720    516K/s  估时 16s
  • ^C
  • fdipzone@ubuntu:~/Downloads$ wget -c -O test.rar http://demo.fdipzone.com/demo.php
  • --2013-06-30 16:53:31--  http://demo.fdipzone.com/demo.php
  • 正在解析主机 demo.fdipzone.com... 127.0.0.1
  • 正在连接 demo.fdipzone.com|127.0.0.1|:80... 已连接。
  • 已发出 HTTP 请求,正在等待回应... 206 Partial Content
  • 长度: 10445121 (10.0M),7822971 (7.5M) 字节剩余 [application/octet-stream]
  • 正在保存至: “test.rar”

  • 100%[++++++++++++++++++++++++=========================================================================>] 10,445,121   543K/s   花时 14s

  • 2013-06-30 16:53:45 (543 KB/s) - 已保存 “test.rar” [10445121/10445121])

  • 可以看到会从断点的位置(%20)开始下载。

源码下载地址:点击下载
  版权声明:本文为博主原创文章,未经博主允许不得转载。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-104557-1-1.html 上篇帖子: PHP5.4的变化关注---What has changed in PHP 5.4.x 下篇帖子: PHP 判断数组是否为空的5大方法
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表