FileDownload.class.php

    1. <?php
    2. /** php下载类,支持断点续传
    3. *   Date:   2013-06-30
    4. *   Author: fdipzone
    5. *   Ver:    1.0
    6. *
    7. *   Func:
    8. *   download: 下载文件
    9. *   setSpeed: 设置下载速度
    10. *   getRange: 获取header中Range
    11. */
    12. class FileDownload{ // class start
    13. private $_speed = 512;   // 下载速度
    14. /** 下载
    15. * @param String  $file   要下载的文件路径
    16. * @param String  $name   文件名称,为空则与下载的文件名称一样
    17. * @param boolean $reload 是否开启断点续传
    18. */
    19. public function download($file, $name='', $reload=false){
    20. if(file_exists($file)){
    21. if($name==''){
    22. $name = basename($file);
    23. }
    24. $fp = fopen($file, 'rb');
    25. $file_size = filesize($file);
    26. $ranges = $this->getRange($file_size);
    27. header('cache-control:public');
    28. header('content-type:application/octet-stream');
    29. header('content-disposition:attachment; filename='.$name);
    30. if($reload && $ranges!=null){ // 使用续传
    31. header('HTTP/1.1 206 Partial Content');
    32. header('Accept-Ranges:bytes');
    33. // 剩余长度
    34. header(sprintf('content-length:%u',$ranges['end']-$ranges['start']));
    35. // range信息
    36. header(sprintf('content-range:bytes %s-%s/%s', $ranges['start'], $ranges['end'], $file_size));
    37. // fp指针跳到断点位置
    38. fseek($fp, sprintf('%u', $ranges['start']));
    39. }else{
    40. header('HTTP/1.1 200 OK');
    41. header('content-length:'.$file_size);
    42. }
    43. while(!feof($fp)){
    44. echo fread($fp, round($this->_speed*1024,0));
    45. ob_flush();
    46. //sleep(1); // 用于测试,减慢下载速度
    47. }
    48. ($fp!=null) && fclose($fp);
    49. }else{
    50. return '';
    51. }
    52. }
    53. /** 设置下载速度
    54. * @param int $speed
    55. */
    56. public function setSpeed($speed){
    57. if(is_numeric($speed) && $speed>16 && $speed<4096){
    58. $this->_speed = $speed;
    59. }
    60. }
    61. /** 获取header range信息
    62. * @param  int   $file_size 文件大小
    63. * @return Array
    64. */
    65. private function getRange($file_size){
    66. if(isset($_SERVER['HTTP_RANGE']) && !emptyempty($_SERVER['HTTP_RANGE'])){
    67. $range = $_SERVER['HTTP_RANGE'];
    68. $range = preg_replace('/[\s|,].*/', '', $range);
    69. $range = explode('-', substr($range, 6));
    70. if(count($range)<2){
    71. $range[1] = $file_size;
    72. }
    73. $range = array_combine(array('start','end'), $range);
    74. if(emptyempty($range['start'])){
    75. $range['start'] = 0;
    76. }
    77. if(emptyempty($range['end'])){
    78. $range['end'] = $file_size;
    79. }
    80. return $range;
    81. }
    82. return null;
    83. }
    84. } // class end
    85. ?>
    86. demo
    87. [codes=php]
    88. <?php
    89. require('FileDownload.class.php');
    90. $file = 'book.zip';
    91. $name = time().'.zip';
    92. $obj = new FileDownload();
    93. $flag = $obj->download($file, $name);
    94. //$flag = $obj->download($file, $name, true); // 断点续传
    95. if(!$flag){
    96. echo 'file not exists';
    97. }
    98. ?>
    99. 断点续传测试方法:
    100. 使用linux wget命令去测试下载, wget -c -O file http://xxx
    101. 1.先关闭断点续传
    102. $flag = $obj->download($file, $name);
    103. [plain] view plaincopy
    104. fdipzone@ubuntu:~/Downloads$ wget -O test.rar http://demo.fdipzone.com/demo.php
    105. --2013-06-30 16:52:44--  http://demo.fdipzone.com/demo.php
    106. 正在解析主机 demo.fdipzone.com... 127.0.0.1
    107. 正在连接 demo.fdipzone.com|127.0.0.1|:80... 已连接。
    108. 已发出 HTTP 请求,正在等待回应... 200 OK
    109. 长度: 10445120 (10.0M) [application/octet-stream]
    110. 正在保存至: “test.rar”
    111. 30% [============================>                                                                     ] 3,146,580    513K/s  估时 14s
    112. ^C
    113. fdipzone@ubuntu:~/Downloads$ wget -c -O test.rar http://demo.fdipzone.com/demo.php
    114. --2013-06-30 16:52:57--  http://demo.fdipzone.com/demo.php
    115. 正在解析主机 demo.fdipzone.com... 127.0.0.1
    116. 正在连接 demo.fdipzone.com|127.0.0.1|:80... 已连接。
    117. 已发出 HTTP 请求,正在等待回应... 200 OK
    118. 长度: 10445120 (10.0M) [application/octet-stream]
    119. 正在保存至: “test.rar”
    120. 30% [============================>                                                                     ] 3,146,580    515K/s  估时 14s
    121. ^C
    122. 可以看到,wget -c不能断点续传
    123. 2.开启断点续传
    124. $flag = $obj->download($file, $name, true);
    125. [plain] view plaincopy
    126. fdipzone@ubuntu:~/Downloads$ wget -O test.rar http://demo.fdipzone.com/demo.php
    127. --2013-06-30 16:53:19--  http://demo.fdipzone.com/demo.php
    128. 正在解析主机 demo.fdipzone.com... 127.0.0.1
    129. 正在连接 demo.fdipzone.com|127.0.0.1|:80... 已连接。
    130. 已发出 HTTP 请求,正在等待回应... 200 OK
    131. 长度: 10445120 (10.0M) [application/octet-stream]
    132. 正在保存至: “test.rar”
    133. 20% [==================>                                                                               ] 2,097,720    516K/s  估时 16s
    134. ^C
    135. fdipzone@ubuntu:~/Downloads$ wget -c -O test.rar http://demo.fdipzone.com/demo.php
    136. --2013-06-30 16:53:31--  http://demo.fdipzone.com/demo.php
    137. 正在解析主机 demo.fdipzone.com... 127.0.0.1
    138. 正在连接 demo.fdipzone.com|127.0.0.1|:80... 已连接。
    139. 已发出 HTTP 请求,正在等待回应... 206 Partial Content
    140. 长度: 10445121 (10.0M),7822971 (7.5M) 字节剩余 [application/octet-stream]
    141. 正在保存至: “test.rar”
    142. 100%[++++++++++++++++++++++++=========================================================================>] 10,445,121   543K/s   花时 14s
    143. 2013-06-30 16:53:45 (543 KB/s) - 已保存 “test.rar” [10445121/10445121])
    144. 可以看到会从断点的位置(%20)开始下载。
    145. 源码下载地址:<a href="http://download.csdn.net/detail/fdipzone/5676439" target="_blank">点击下载 </a>
    146. 摘自:http://blog.csdn.net/fdipzone/article/details/9208221
    147. PHP上传实现断点续传文件的方法:
    148. 其实说简单点就是通过这个变量$_SERVER['HTTP_RANGE']取得用户请求的文件的range,然后程序去控制文件的输出。比如第一次请求一个文件的从0到999字节,第二次请求1000到1999字节,以此类推,每次请求1000字节的内容,然后程序通过fseek函数去取得对应的文件位置,然后输出。
    149. [codes=php]
    150. $fname = './05e58c19552bb26b158f6621a6650899';
    151. $fp = fopen($fname,'rb');
    152. $fsize = filesize($fname);
    153. if (isset($_SERVER['HTTP_RANGE']) && ($_SERVER['HTTP_RANGE'] != "") && preg_match("/^bytes=([0-9]+)-$/i", $_SERVER['HTTP_RANGE'], $match) && ($match[1] < $fsize)) {
    154. $start = $match[1];
    155. } else {
    156. $start = 0;
    157. }
    158. @header("Cache-control: public");
    159. @header("Pragma: public");
    160. if ($start > 0) {
    161. fseek($fp, $start);
    162. Header("HTTP/1.1 206 Partial Content");
    163. Header("Content-Length: " . ($fsize - $start));
    164. Header("Content-Ranges: bytes" . $start . "-" . ($fsize - 1) . "/" . $fsize);
    165. } else {
    166. header("Content-Length: $fsize");
    167. Header("Accept-Ranges: bytes");
    168. }
    169. @header("Content-Type: application/octet-stream");
    170. @header("Content-Disposition: attachment;filename=1.rm");
    171. fpassthru($fp);

php download断点的更多相关文章

  1. Java实现多线程断点下载(下载过程中可以暂停)

    线程可以理解为下载的通道,一个线程就是一个文件的下载通道,多线程也就是同时开启好几个下载通道.当服务器提供下载服务时,使用下载者是共享带宽的,在优先级相同的情况下,总服务器会对总下载线程进行平均分配. ...

  2. 安卓(android)之实现断点下载功能

    一.建立实体类 1.文件实体类 package com.example.zjw.myapplication.dao; import java.io.Serializable; /** * 预下载文件实 ...

  3. 【Java EE 学习 22 下】【单线程下载】【单线程断点下载】【多线程下载】

    一.文件下载简述 1.使用浏览器从网页上下载文件,Servlet需要增加一些响应头信息 (1)response.setContentType("application/force-downl ...

  4. Android 学习之--android多线程断点下载

    我们平时都用"迅雷"下载软件,当下载到一半的时候突然断网,下次开启的时候能够从上次下载的地方继续下载,而且下载速度很快,那么这是怎么做到的呢! 其实它的“快”其实就是多线程的下载实 ...

  5. Spring 4.3.2下实现http多次断点下载

    其实跟 spring 无关,如果是直接下载资源很多 web sever 不用程序就直接实现了断点. 但我们的应用是 download?url=xxxx 这种方式 下载资源由 download 来负责, ...

  6. Android 学习笔记之使用多线程实现断点下载...

    PS:莫名其妙的迷茫... 学习内容: 1.使用多线程实现文件下载...   多线程下载是加快下载速度的一种方式..通过开启多个线程去执行一个任务..可以使任务的执行速度变快..多线程的任务下载时常都 ...

  7. 如何远程断点调试本地localhost项目

    前言 对于一般开发网站的IDE自带的服务器是都跑在 localhost 地址上的.(如下图的asp.net) 而这种地址是只能在本机通过 localhost 或 127.0.0.1 地址访问到,而无法 ...

  8. 33、多线程断点下载的实现&界面的更新

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...

  9. Android(java)学习笔记216:多线程断点下载的原理(Android实现)

    之前在Android(java)学习笔记215中,我们从JavaSE的角度去实现了多线程断点下载,下面从Android角度实现这个断点下载: 1.新建一个Android工程: (1)其中我们先实现布局 ...

随机推荐

  1. HDU5860 (递推)

    Problem Death Sequence 题目大意 排成一行的约瑟夫问题. n个人排成一行,从第一个人开始,每个k个人报数,报到数的人被杀死,剩下的人重新排成一行再报数. 一共q个询问,每次询问第 ...

  2. Magento创建configurable产品的要点

    接着上一篇用API创建可配置的产品Configurable Product说事.Magento的产品类型可分为Simple Product.Group Product.Configurable Pro ...

  3. 第一个Sprint冲刺第四天

    讨论成员:邵家文.李新.朱浩龙.陈俊金 讨论问题:掌握计时技术的知识 讨论地点:qq网络 进展:即将开始对计时技术代码的编写

  4. 打开office弹出steup error 的解决办法

    找到 C:\Program Files\Common Files\Microsoft Shared\OFFICE12\Office Setup Controller 将这个文件夹删除

  5. cocos引擎v2.1版本android 编译问题解决办法 (cocos2d-x-3.4rc1)

    下载了最新版的cocos v2.1.2beta,使用cocos.exe来创建项目,而且在最下方的附件功能里还勾选了“支持x86架构cpu”这个选项,导致使用build_native.py编译不通过,以 ...

  6. Java字符串null相加

    Java字符串null相加 最近和同事讨论了下面的一段代码: String a = null; a += a; System.out.println(a); 运行结果: nullnull 本着学习的态 ...

  7. Install GD on mac

    Lots of bioinformatics software are based on perl. Some of them, for example, Circos, NGS toolkit... ...

  8. ubuntu默认root密码

    安装完Kubuntu后一直都是用我的用户名bbking登录, 一直没想到root的问题, 以为每次sudo输入的密码就是我的root密码. 刚才为了修改文件夹的所有者,想使用su root切换到roo ...

  9. Vimium 快捷键记录

    , <c-e> : Scroll down k, <c-y> : Scroll up h : Scroll left l : Scroll right gg : Scroll ...

  10. CentOS 6.2 OpenVPN 搭建

    一.yum 安装. 二.下载 easy-rsa 3.0 三.生成根证书.服务器.客户端证书.ta 生成流程: wget -c https://github.com/OpenVPN/easy-rsa/a ...