<?php  
/** php下载类,支持断点续传 
*   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;  
    }  
}
$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';  
}  
?>

DEMO下载地址:https://dwz.cn/ORcEz9fz

最新文章

  1. BZOJ3670 [Noi2014]动物园
  2. jQuery 增加 删除 修改select option .
  3. 第三章Git使用入门--读书笔记
  4. clearfix--清除浮动
  5. CLR via C#(15)--String,熟悉而又陌生
  6. swift语言学习之UITableView分割线左边到头的解决
  7. PN-Traniger
  8. 兼容IE6/IE7/IE8/FireFox的css hack
  9. 解决IE6下DIV无法实现1px高度问题
  10. where can I find source of com.android.internal.R.styleable.AlertDialog_multiChoiceItemLayout?
  11. BZOJ 3907: 网格( 组合数 + 高精度 )
  12. Caused by: java.lang.ClassNotFoundException: javax.transaction.TransactionManager
  13. 判断UA这种事不能说的太明。
  14. 面向切面编程(Aop)
  15. Anaconda+用conda创建python虚拟环境
  16. vue环境搭建与创建第一个vuejs文件
  17. 隐藏状态栏,toolbar前面空格问题,editText圆角
  18. Spring Boot的日志配置
  19. python学习Day13 函数的嵌套定义、global、nonlocal关键字、闭包及闭包的运用场景、装饰器
  20. HBase的Write Ahead Log (WAL) —— 整体架构、线程模型【转】

热门文章

  1. Android:webView加载h5网页视频,播放不了,以及横屏全屏的问题和实现自定义加载进度条的效果
  2. 快速排序中BUG int 与 int *
  3. 字符串加u的特殊需求
  4. 获取URL某个参数
  5. u-boot之内核是怎么启动的
  6. Java并发-ThreadGroup获取所有线程
  7. 快速掌握Ajax-Ajax基础实例(Ajax返回Json在Java中的实现)
  8. SQL注入漏洞的原理
  9. 如何通过class文件来查看java的版本
  10. 在iOS 8及以后使用UIAlertController 等各种弹出警告通知