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

[经验分享] PHP 关于文件上传下载 断点续传问题

[复制链接]

尚未签到

发表于 2015-8-23 14:45:16 | 显示全部楼层 |阅读模式
  让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协议实现文件下载,所以也只看了一部分,并没有看全。
  如果服务器成功收到该请求,并且没有出现任何错误,则会返回类似下面的数据:
  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 具体数据的处理




1 /** $file_size  文件大小 */
2  function getRange($file_size){
3     $range = isset($_SERVER['HTTP_RANGE'])?$_SERVER['HTTP_RANGE']:null;
4     if(!empty($range)){
5         $range = preg_replace('/[\s|,].*/', '', $range);
6         $range = explode('-',substr($range,6));
7         if (count($range) < 2 ) {
8             $range[1] = $file_size;
9         }
10         $range = array_combine(array('start','end'),$range);
11         if (empty($range['start'])) {
12             $range['start'] = 0;
13         }
14         if (!isset ($range['end']) || empty($range['end'])) {
15             $range['end'] = $file_size;
16         }
17         return $range;
18     }
19     return null;
20 }
  假设文件的地址为 $file_path




1 $speed = 512;//此参数为下载最大速度
2  $pos = strrpos($file_path, "/");
3  $file_name = substr($file_path, $pos+1);
4 $file_size = filesize($file_path);
5 $ranges = getRange($file_size);
6 $fh =  fopen($file_path, "rb");
7 header('Cache-control: public');
8 header('Content-Type: application/octet-stream');
9 header('Content-Disposition: attachment; filename='.$file_name);
10 if ($ranges != null) {
11     header('HTTP/1.1 206 Partial Content');
12     header('Accept-Ranges: bytes');
13     header(sprintf('Content-Length: %u',$ranges['end'] - $ranges['start']));
14     header(sprintf('Content-Range: bytes %s-%s/%s', $ranges['start'], $ranges['end'], $file_size));
15     fseek($fh, sprintf('%u',$ranges['start']));
16 }else{
17     header("HTTP/1.1 200 OK");
18     header(sprintf('Content-Length: %s', $file_size));
19 }
20 while(!feof($fh))
21 {
22     echo  fread($fh, round($speed*1024, 0));
23     ob_flush();
24     sleep(1);
25 }
26 ($fh != null) && fclose($fh);
  基本如此 就可以解决一般性文件的断点续传或者下载了

运维网声明 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-103046-1-1.html 上篇帖子: ZendStudio php WebService制作一:简单WebService Demo 下篇帖子: 简单说说PHP优化那些事
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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