<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>http://jackxiang.com/index.php</link> 
<description><![CDATA[赢在IT，Playin' with IT,Focus on Killer Application,Marketing Meets Technology.]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></copyright>
<item>
<link>http://jackxiang.com/post//</link>
<title><![CDATA[[实践OK]Web服务器(如Apache、Nginx)会默认开启对断点续传的支持，php支持断点续传的文件下载类，PHP上传实现断点续传文件的方法。]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[Php/Js/Shell/Go]]></category>
<pubDate>Wed, 19 Nov 2014 09:05:57 +0000</pubDate> 
<guid>http://jackxiang.com/post//</guid> 
<description>
<![CDATA[ 
	背景：大文件的断点续传，有时网络波动啥的，需要断点从已经下载位置续传下载文件，对于没有传过的文件再次从开始下载就麻烦了，这块http协议支持的，Apache和Nginx都支持这样的方法实现了从某个部分进行断点下载。<br/>服务器是否支持断点续传的判断：<br/>更多 0<br/>断点续传 linux wget 服务器 curl<br/>通常情况下，Web服务器(如Apache)会默认开启对断点续传的支持。因此，如果直接通过Web服务器来提供文件的下载，可以不必做特别的配置，即可享受到断点续传的好处。断点续传是在发起HTTP请求的时候加入RANGE头来告诉服务器客户端已经下载了多少字节。等所有这些请求都返回之后，再把得到的内容一块一块的拼接起来得到完整的资源。<br/><br/>Resumable download file Web服务器(如Apache)默认开启断点续传<br/><br/>你可以通过以下的命令来测试一下。<br/><br/>Linux 测试服务器是否支持断点续传<br/><br/>localhost [~]# wget -S http://httpd.apache.org/images/httpd_logo_wide_new.png 2&gt;&amp;1 &#124; grep ‘Accept-Ranges’ <br/>&nbsp;&nbsp;Accept-Ranges: bytes<br/><br/>输出结果 Accept-Ranges: bytes ，说明服务器支持按字节下载。<br/><br/>curl 命令发送字节范围下载<br/><br/>curl –range 0-99 http://images.apple.com/home/images/billboard_iphone_hero.jpg<br/><br/>这样可以到最开始99字节，结果如下图：<br/><br/>curl range bytes request curl 命令发送字节范围请求<br/><br/>说明从服务器端按字节范围下载是完全没有问题的。<br/><br/>现在我们尝试以下方式：<br/><br/>1、一次性下载整个图片。<br/><br/>localhost [~]# curl –range 0-98315 http://images.apple.com/home/images/billboard_iphone_hero.jpg &gt; test.jpg <br/>&nbsp;&nbsp;% Total&nbsp;&nbsp;&nbsp;&nbsp;% Received % Xferd&nbsp;&nbsp;Average Speed&nbsp;&nbsp; Time&nbsp;&nbsp;&nbsp;&nbsp;Time&nbsp;&nbsp;&nbsp;&nbsp; Time&nbsp;&nbsp;Current <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dload&nbsp;&nbsp;Upload&nbsp;&nbsp; Total&nbsp;&nbsp; Spent&nbsp;&nbsp;&nbsp;&nbsp;Left&nbsp;&nbsp;Speed <br/>100 98316&nbsp;&nbsp;100 98316&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp; 524k&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 –:–:– –:–:– –:—:—&nbsp;&nbsp;527k<br/><br/>完成后，test.jpg完全等于billboard_iphone_hero.jpg，文件大小为98,316 字节。<br/><br/>实践如下：我的Nginx服务器，请求下看是否支持，如下：<br/>1）实践下下载这块的header返回头有Accept-Ranges: bytes证明Nginx也是支持断点续传下载的：<br/><textarea name="code" class="php" rows="15" cols="100">
 wget -S http://jackxiang.com/template/trielegant/images/bridge-banner-nine.jpg
--2014-11-19 22:46:51--&nbsp;&nbsp;http://jackxiang.com/template/trielegant/images/bridge-banner-nine.jpg
正在解析主机 jackxiang.com... 119.10.6.23
正在连接 jackxiang.com&#124;119.10.6.23&#124;:80... 已连接。
已发出 HTTP 请求，正在等待回应... 
&nbsp;&nbsp;HTTP/1.1 200 OK
&nbsp;&nbsp;Server: nginx
&nbsp;&nbsp;Date: Wed, 19 Nov 2014 14:34:46 GMT
&nbsp;&nbsp;Content-Type: image/jpeg
&nbsp;&nbsp;Content-Length: 7052
&nbsp;&nbsp;Last-Modified: Fri, 07 Nov 2014 05:06:12 GMT
&nbsp;&nbsp;Connection: keep-alive
&nbsp;&nbsp;ETag: &quot;545c5344-1b8c&quot;
&nbsp;&nbsp;Expires: Fri, 19 Dec 2014 14:34:46 GMT
&nbsp;&nbsp;Cache-Control: max-age=2592000
&nbsp;&nbsp;Accept-Ranges: bytes
长度：7052 (6.9K) [image/jpeg]
正在保存至: “bridge-banner-nine.jpg.1”
2）通地加上grep指令有返回即是支持的：
</textarea><br/><textarea name="code" class="php" rows="15" cols="100">
wget -S http://jackxiang.com/template/trielegant/images/bridge-banner-nine.jpg 2&gt;&amp;1 &#124; grep &#039;Accept-Ranges&#039; 
&nbsp;&nbsp;Accept-Ranges: bytes
</textarea><br/><textarea name="code" class="php" rows="15" cols="100">
3）用curl实现下载一段并保存到本地：
[codes=php]
 curl --range 0-99 http://jackxiang.com/template/trielegant/images/bridge-banner-nine.jpg&nbsp;&nbsp;&gt; bridge-banner-nine.jpg
&nbsp;&nbsp;% Total&nbsp;&nbsp;&nbsp;&nbsp;% Received % Xferd&nbsp;&nbsp;Average Speed&nbsp;&nbsp; Time&nbsp;&nbsp;&nbsp;&nbsp;Time&nbsp;&nbsp;&nbsp;&nbsp; Time&nbsp;&nbsp;Current
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dload&nbsp;&nbsp;Upload&nbsp;&nbsp; Total&nbsp;&nbsp; Spent&nbsp;&nbsp;&nbsp;&nbsp;Left&nbsp;&nbsp;Speed
&nbsp;&nbsp;0&nbsp;&nbsp; 100&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp; 100&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;729&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 --:--:-- --:--:-- --:--:--&nbsp;&nbsp;1886
</textarea><br/>（1）Curl包含range的请求头是这样的：<br/><textarea name="code" class="php" rows="15" cols="100">
GET /template/trielegant/images/bridge-banner-nine.jpg HTTP/1.1
Request Version: HTTP/1.1
Range: bytes=0-108
User-Agent: curl/7.19.7 (i386-redhat-linux-gnu) libcurl/7.19.7 NSS/3.14.0.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2
Host: jackxiang.com
Accept: */*
</textarea><br/>（2）其抓包Nginx的返回头是这样：<br/>HTTP/1.1 206 Partial Content<br/>Server: nginx<br/>Date: Wed, 19 Nov 2014 14:45:07 GMT<br/>Content-Type: image/jpeg<br/>Content-Length: 109<br/>Last-Modified: Fri, 07 Nov 2014 05:06:12 GMT<br/>Connection: keep-alive<br/>ETag: &quot;545c5344-1b8c&quot;<br/>Expires: Fri, 19 Dec 2014 14:45:07 GMT<br/>Cache-Control: max-age=2592000<br/>Content-Range: bytes 0-108/7052<br/><br/><br/>4）通过前面的curl及wget联合起来，先后组合起来实现一个断点下载整个图片，并看其服务器返回头（curl已经下了前面的108，后从109开始wget：<br/>（1）先保存一部分到108：<br/><textarea name="code" class="php" rows="15" cols="100">
root@192.168.0.6:~# curl --range 0-108 http://jackxiang.com/template/trielegant/images/bridge-banner-nine.jpg&nbsp;&nbsp;&gt; bridge-banner-nine.jpg
&nbsp;&nbsp;% Total&nbsp;&nbsp;&nbsp;&nbsp;% Received % Xferd&nbsp;&nbsp;Average Speed&nbsp;&nbsp; Time&nbsp;&nbsp;&nbsp;&nbsp;Time&nbsp;&nbsp;&nbsp;&nbsp; Time&nbsp;&nbsp;Current
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dload&nbsp;&nbsp;Upload&nbsp;&nbsp; Total&nbsp;&nbsp; Spent&nbsp;&nbsp;&nbsp;&nbsp;Left&nbsp;&nbsp;Speed
109&nbsp;&nbsp; 109&nbsp;&nbsp;109&nbsp;&nbsp; 109&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;907&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 --:--:-- --:--:-- --:--:--&nbsp;&nbsp;1912
</textarea><br/><br/>（2）再通过wget的断点续传下载命令-c，请求剩下的部分（Content-Range: bytes 109-7051/7052）：<br/> A）加上-S看返回头， -S,&nbsp;&nbsp;--server-response&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 打印服务器响应。：<br/><textarea name="code" class="php" rows="15" cols="100">
root@192.168.0.6:~# wget -S -c http://jackxiang.com/template/trielegant/images/bridge-banner-nine.jpg
--2014-11-19 22:53:16--&nbsp;&nbsp;http://jackxiang.com/template/trielegant/images/bridge-banner-nine.jpg
正在解析主机 jackxiang.com... 119.10.6.23
正在连接 jackxiang.com&#124;119.10.6.23&#124;:80... 已连接。
已发出 HTTP 请求，正在等待回应... 
&nbsp;&nbsp;HTTP/1.1 206 Partial Content
&nbsp;&nbsp;Server: nginx
&nbsp;&nbsp;Date: Wed, 19 Nov 2014 14:41:12 GMT
&nbsp;&nbsp;Content-Type: image/jpeg
&nbsp;&nbsp;Content-Length: 6943
&nbsp;&nbsp;Last-Modified: Fri, 07 Nov 2014 05:06:12 GMT
&nbsp;&nbsp;Connection: keep-alive
&nbsp;&nbsp;ETag: &quot;545c5344-1b8c&quot;
&nbsp;&nbsp;Expires: Fri, 19 Dec 2014 14:41:12 GMT
&nbsp;&nbsp;Cache-Control: max-age=2592000
&nbsp;&nbsp;Content-Range: bytes 109-7051/7052
长度：7052 (6.9K)，6943 (6.8K) 字节剩余 [image/jpeg]
正在保存至: “bridge-banner-nine.jpg”

100%[+=============================================================================================================&gt;] 7,052&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --.-K/s&nbsp;&nbsp; in 0.1s&nbsp;&nbsp;&nbsp;&nbsp;

2014-11-19 22:53:16 (68.2 KB/s) - 已保存 “bridge-banner-nine.jpg” [7052/7052])
</textarea><br/><br/>B）发起头如下，也就是说经curl保存一部分后，wget通过-c参数时，后面它会去读取目前文件大小，后写在http头里去找服务端要，请求头如下：<br/><textarea name="code" class="php" rows="15" cols="100">
GET /template/trielegant/images/bridge-banner-nine.jpg HTTP/1.0
Request Version: HTTP/1.0
Range: bytes=109-
User-Agent: Wget/1.12 (linux-gnu)
Accept: */*
Host: jackxiang.com
Connection: Keep-Alive
</textarea><br/><br/>注意：字节是从0开始，结束字节为总字节长度 减 1。<br/>来自：http://ju.outofmemory.cn/entry/23646<br/>Nginx：http://chenzhenianqing.cn/articles/926.html<br/><br/> php 支持断点续传，主要依靠HTTP协议中 header HTTP_RANGE实现。<br/><br/>HTTP断点续传原理<br/>Http头 Range、Content-Range()<br/>HTTP头中一般断点下载时才用到Range和Content-Range实体头，<br/>Range用户请求头中，指定第一个字节的位置和最后一个字节的位置，如（Range：200-300）<br/>Content-Range用于响应头<br/><br/>请求下载整个文件: <br/>GET /test.rar HTTP/1.1 <br/>Connection: close <br/>Host: 116.1.219.219 <br/>Range: bytes=0-801 //一般请求下载整个文件是bytes=0- 或不用这个头<br/><br/>一般正常回应 <br/>HTTP/1.1 200 OK <br/>Content-Length: 801&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>Content-Type: application/octet-stream <br/>Content-Range: bytes 0-800/801 //801:文件总大小<br/><br/>FileDownload.class.php<br/><textarea name="code" class="php" rows="15" cols="100">
&nbsp;&nbsp;&nbsp;&nbsp;&lt;?php&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;/** php下载类,支持断点续传 
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp; Date:&nbsp;&nbsp; 2013-06-30 
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp; Author: fdipzone 
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp; Ver:&nbsp;&nbsp;&nbsp;&nbsp;1.0 
&nbsp;&nbsp;&nbsp;&nbsp;* 
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp; Func: 
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp; download: 下载文件 
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp; setSpeed: 设置下载速度 
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp; getRange: 获取header中Range 
&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;class FileDownload&#123; // class start&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private $_speed = 512;&nbsp;&nbsp; // 下载速度&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/** 下载 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* @param String&nbsp;&nbsp;$file&nbsp;&nbsp; 要下载的文件路径 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* @param String&nbsp;&nbsp;$name&nbsp;&nbsp; 文件名称,为空则与下载的文件名称一样 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* @param boolean $reload 是否开启断点续传 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public function download($file, $name=&#039;&#039;, $reload=false)&#123;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(file_exists($file))&#123;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if($name==&#039;&#039;)&#123;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$name = basename($file);&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$fp = fopen($file, &#039;rb&#039;);&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$file_size = filesize($file);&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$ranges = $this-&gt;getRange($file_size);&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;header(&#039;cache-control:public&#039;);&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;header(&#039;content-type:application/octet-stream&#039;);&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;header(&#039;content-disposition:attachment; filename=&#039;.$name);&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if($reload &amp;&amp; $ranges!=null)&#123; // 使用续传&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;header(&#039;HTTP/1.1 206 Partial Content&#039;);&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;header(&#039;Accept-Ranges:bytes&#039;);&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 剩余长度&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;header(sprintf(&#039;content-length:%u&#039;,$ranges[&#039;end&#039;]-$ranges[&#039;start&#039;]));&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// range信息&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;header(sprintf(&#039;content-range:bytes %s-%s/%s&#039;, $ranges[&#039;start&#039;], $ranges[&#039;end&#039;], $file_size));&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// fp指针跳到断点位置&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fseek($fp, sprintf(&#039;%u&#039;, $ranges[&#039;start&#039;]));&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;else&#123;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;header(&#039;HTTP/1.1 200 OK&#039;);&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;header(&#039;content-length:&#039;.$file_size);&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(!feof($fp))&#123;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo fread($fp, round($this-&gt;_speed*1024,0));&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ob_flush();&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//sleep(1); // 用于测试,减慢下载速度&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;($fp!=null) &amp;&amp; fclose($fp);&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;else&#123;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return &#039;&#039;;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/** 设置下载速度 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* @param int $speed 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public function setSpeed($speed)&#123;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(is_numeric($speed) &amp;&amp; $speed&gt;16 &amp;&amp; $speed&lt;4096)&#123;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;_speed = $speed;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/** 获取header range信息 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* @param&nbsp;&nbsp;int&nbsp;&nbsp; $file_size 文件大小 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* @return Array 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private function getRange($file_size)&#123;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(isset($_SERVER[&#039;HTTP_RANGE&#039;]) &amp;&amp; !empty($_SERVER[&#039;HTTP_RANGE&#039;]))&#123;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$range = $_SERVER[&#039;HTTP_RANGE&#039;];&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$range = preg_replace(&#039;/[&#92;s&#124;,].*/&#039;, &#039;&#039;, $range);&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$range = explode(&#039;-&#039;, substr($range, 6));&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(count($range)&lt;2)&#123;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$range[1] = $file_size;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$range = array_combine(array(&#039;start&#039;,&#039;end&#039;), $range);&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(empty($range[&#039;start&#039;]))&#123;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$range[&#039;start&#039;] = 0;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(empty($range[&#039;end&#039;]))&#123;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$range[&#039;end&#039;] = $file_size;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return $range;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return null;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&#125; // class end&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;?&gt;&nbsp;&nbsp;

demo
[codes=php]

&nbsp;&nbsp;&nbsp;&nbsp;&lt;?php&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;require(&#039;FileDownload.class.php&#039;);&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;$file = &#039;book.zip&#039;;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;$name = time().&#039;.zip&#039;;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;$obj = new FileDownload();&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;$flag = $obj-&gt;download($file, $name);&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;//$flag = $obj-&gt;download($file, $name, true); // 断点续传&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;if(!$flag)&#123;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo &#039;file not exists&#039;;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;?&gt;&nbsp;&nbsp;

断点续传测试方法:
使用linux wget命令去测试下载, wget -c -O file http://xxx

1.先关闭断点续传
$flag = $obj-&gt;download($file, $name);
[plain] view plaincopy

&nbsp;&nbsp;&nbsp;&nbsp;fdipzone@ubuntu:~/Downloads$ wget -O test.rar http://demo.fdipzone.com/demo.php&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;--2013-06-30 16:52:44--&nbsp;&nbsp;http://demo.fdipzone.com/demo.php&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;正在解析主机 demo.fdipzone.com... 127.0.0.1&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;正在连接 demo.fdipzone.com&#124;127.0.0.1&#124;:80... 已连接。&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;已发出 HTTP 请求，正在等待回应... 200 OK&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;长度： 10445120 (10.0M) [application/octet-stream]&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;正在保存至: “test.rar”&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;30% [============================&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ] 3,146,580&nbsp;&nbsp;&nbsp;&nbsp;513K/s&nbsp;&nbsp;估时 14s&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;^C&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;fdipzone@ubuntu:~/Downloads$ wget -c -O test.rar http://demo.fdipzone.com/demo.php&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;--2013-06-30 16:52:57--&nbsp;&nbsp;http://demo.fdipzone.com/demo.php&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;正在解析主机 demo.fdipzone.com... 127.0.0.1&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;正在连接 demo.fdipzone.com&#124;127.0.0.1&#124;:80... 已连接。&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;已发出 HTTP 请求，正在等待回应... 200 OK&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;长度： 10445120 (10.0M) [application/octet-stream]&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;正在保存至: “test.rar”&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;30% [============================&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ] 3,146,580&nbsp;&nbsp;&nbsp;&nbsp;515K/s&nbsp;&nbsp;估时 14s&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;^C&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;可以看到,wget -c不能断点续传&nbsp;&nbsp;


2.开启断点续传
$flag = $obj-&gt;download($file, $name, true);
[plain] view plaincopy

&nbsp;&nbsp;&nbsp;&nbsp;fdipzone@ubuntu:~/Downloads$ wget -O test.rar http://demo.fdipzone.com/demo.php&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;--2013-06-30 16:53:19--&nbsp;&nbsp;http://demo.fdipzone.com/demo.php&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;正在解析主机 demo.fdipzone.com... 127.0.0.1&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;正在连接 demo.fdipzone.com&#124;127.0.0.1&#124;:80... 已连接。&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;已发出 HTTP 请求，正在等待回应... 200 OK&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;长度： 10445120 (10.0M) [application/octet-stream]&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;正在保存至: “test.rar”&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;20% [==================&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ] 2,097,720&nbsp;&nbsp;&nbsp;&nbsp;516K/s&nbsp;&nbsp;估时 16s&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;^C&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;fdipzone@ubuntu:~/Downloads$ wget -c -O test.rar http://demo.fdipzone.com/demo.php&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;--2013-06-30 16:53:31--&nbsp;&nbsp;http://demo.fdipzone.com/demo.php&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;正在解析主机 demo.fdipzone.com... 127.0.0.1&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;正在连接 demo.fdipzone.com&#124;127.0.0.1&#124;:80... 已连接。&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;已发出 HTTP 请求，正在等待回应... 206 Partial Content&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;长度： 10445121 (10.0M)，7822971 (7.5M) 字节剩余 [application/octet-stream]&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;正在保存至: “test.rar”&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;100%[++++++++++++++++++++++++=========================================================================&gt;] 10,445,121&nbsp;&nbsp; 543K/s&nbsp;&nbsp; 花时 14s&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;2013-06-30 16:53:45 (543 KB/s) - 已保存 “test.rar” [10445121/10445121])&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;可以看到会从断点的位置(%20)开始下载。&nbsp;&nbsp;

源码下载地址：<a href="http://download.csdn.net/detail/fdipzone/5676439" target="_blank">点击下载 </a>
摘自：http://blog.csdn.net/fdipzone/article/details/9208221


PHP上传实现断点续传文件的方法：
其实说简单点就是通过这个变量$_SERVER[&#039;HTTP_RANGE&#039;]取得用户请求的文件的range，然后程序去控制文件的输出。比如第一次请求一个文件的从0到999字节，第二次请求1000到1999字节，以此类推，每次请求1000字节的内容，然后程序通过fseek函数去取得对应的文件位置，然后输出。
[codes=php]
&nbsp;&nbsp;&nbsp;&nbsp;$fname = &#039;./05e58c19552bb26b158f6621a6650899&#039;; 
&nbsp;&nbsp;&nbsp;&nbsp;$fp = fopen($fname,&#039;rb&#039;); 
&nbsp;&nbsp;&nbsp;&nbsp;$fsize = filesize($fname); 
&nbsp;&nbsp;&nbsp;&nbsp;if (isset($_SERVER[&#039;HTTP_RANGE&#039;]) &amp;&amp; ($_SERVER[&#039;HTTP_RANGE&#039;] != &quot;&quot;) &amp;&amp; preg_match(&quot;/^bytes=([0-9]+)-$/i&quot;, $_SERVER[&#039;HTTP_RANGE&#039;], $match) &amp;&amp; ($match[1] &lt; $fsize)) &#123; 
&nbsp;&nbsp;&nbsp;&nbsp;$start = $match[1]; 
&nbsp;&nbsp;&nbsp;&nbsp;&#125; else &#123; 
&nbsp;&nbsp;&nbsp;&nbsp;$start = 0; 
&nbsp;&nbsp;&nbsp;&nbsp;&#125; 
&nbsp;&nbsp;&nbsp;&nbsp;@header(&quot;Cache-control: public&quot;); 
&nbsp;&nbsp;&nbsp;&nbsp;@header(&quot;Pragma: public&quot;); 
&nbsp;&nbsp;&nbsp;&nbsp;if ($start &gt; 0) &#123; 
&nbsp;&nbsp;&nbsp;&nbsp;fseek($fp, $start); 
&nbsp;&nbsp;&nbsp;&nbsp;Header(&quot;HTTP/1.1 206 Partial Content&quot;); 
&nbsp;&nbsp;&nbsp;&nbsp;Header(&quot;Content-Length: &quot; . ($fsize - $start)); 
&nbsp;&nbsp;&nbsp;&nbsp;Header(&quot;Content-Ranges: bytes&quot; . $start . &quot;-&quot; . ($fsize - 1) . &quot;/&quot; . $fsize); 
&nbsp;&nbsp;&nbsp;&nbsp;&#125; else &#123; 
&nbsp;&nbsp;&nbsp;&nbsp;header(&quot;Content-Length: $fsize&quot;); 
&nbsp;&nbsp;&nbsp;&nbsp;Header(&quot;Accept-Ranges: bytes&quot;); 
&nbsp;&nbsp;&nbsp;&nbsp;&#125; 
&nbsp;&nbsp;&nbsp;&nbsp;@header(&quot;Content-Type: application/octet-stream&quot;); 
&nbsp;&nbsp;&nbsp;&nbsp;@header(&quot;Content-Disposition: attachment;filename=1.rm&quot;); 
&nbsp;&nbsp;&nbsp;&nbsp;fpassthru($fp);&nbsp;&nbsp;
</textarea><br/>大家也可以看下Discuz!论坛软件的attachment.php文件是如何实现断点续传的。请看代码：也是通过$_SERVER[&#039;HTTP_RANGE&#039;]取得用户请求的文件的range，具体的大家可以查看其源码分析下。这里我就当抛砖引玉了。<br/><textarea name="code" class="php" rows="15" cols="100">
&nbsp;&nbsp;&nbsp;&nbsp; $range = 0; 
&nbsp;&nbsp;&nbsp;&nbsp;if($readmod == 4) &#123; 
&nbsp;&nbsp;&nbsp;&nbsp;dheader(&#039;Accept-Ranges: bytes&#039;); 
&nbsp;&nbsp;&nbsp;&nbsp;if(!emptyempty($_SERVER[&#039;HTTP_RANGE&#039;])) &#123; 
&nbsp;&nbsp;&nbsp;&nbsp;list($range) = explode(&#039;-&#039;,(str_replace(&#039;bytes=&#039;, &#039;&#039;, $_SERVER[&#039;HTTP_RANGE&#039;]))); 
&nbsp;&nbsp;&nbsp;&nbsp;$rangesize = ($filesize - $range) &gt; 0 ? ($filesize - $range) : 0; 
&nbsp;&nbsp;&nbsp;&nbsp;dheader(&#039;Content-Length: &#039;.$rangesize); 
&nbsp;&nbsp;&nbsp;&nbsp;dheader(&#039;HTTP/1.1 206 Partial Content&#039;); 
&nbsp;&nbsp;&nbsp;&nbsp;dheader(&#039;Content-Range: bytes=&#039;.$range.&#039;-&#039;.($filesize-1).&#039;/&#039;.($filesize)); 
&nbsp;&nbsp;&nbsp;&nbsp;&#125; 
&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;
</textarea><br/>摘自：http://www.yunsec.net/a/special/wzjs/wzbc/php/2010/0731/5120.html<br/><br/>参考：http://www.linuxprobe.com/nginx-upload-module.html<br/>https://www.centos.bz/2015/09/nginx-upload-module-multipart-form-data-resumable/
]]>
</description>
</item><item>
<link>http://jackxiang.com/post//#blogcomment</link>
<title><![CDATA[[评论] [实践OK]Web服务器(如Apache、Nginx)会默认开启对断点续传的支持，php支持断点续传的文件下载类，PHP上传实现断点续传文件的方法。]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://jackxiang.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>