让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);
基本如此 就可以解决一般性文件的断点续传或者下载了
声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
相关课程推荐
javascript是运行在浏览器上的脚本语言,连续多年,被评为全球最受欢迎的编程语言。是前端开发必备三大法器中,最具杀伤力。如果前端开发是降龙十八掌,好么javascript就是第18掌:亢龙有悔。没有它,你的前端生涯是不完整的。《php.cn独孤九贱(3)-JavaScript视频教程》课程特色:php中文网原创幽默段子系列课程,以恶搞,段子为主题风格的php视频教程!轻松的教学风格,简短的教学模式,让同学们在不知不觉中,学会了javascript知识。
JavaScript教程142295次播放
jQuery是一个快速、简洁的JavaScript框架。设计的宗旨是“write Less,Do More”,即倡导写更少的代码,做更多的事情。它封装JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,优化HTML文档操作、事件处理、动画设计和Ajax交互。
核心特性可以总结为:具有独特的链式语法和短小清晰的多功能接口;具有高效灵活的css选择器,并且可对CSS选择器进行扩展;拥有便捷的插件扩展机制和丰富的插件。兼容各种主流浏览器,如IE 6.0+、FF 1.5+、Safari 2.0+、Opera 9.0+等,是全球最流行的前端开发框架之一。PHP中文网根据最新版本,独家录制jQuery最新视频教程,回馈PHP中文网的新老用户。
jQuery教程116798次播放
jQuery是最流行的JS函数库,封装了许多实用的功能,其中最引人入胜的就是Ajax。
jQuery中的Ajax操作,语法简单,操作方便,使Ajax从未如此轻松,前端人员从此不再为与服务器异步交互而发愁,本套课程,精选了最常用的几个方法,从基本的语法到每个参数,再到具体实例进行了全面的讲解。
AJAX教程16508次播放
Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。
Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。
Git 与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持
JavaScript教程14226次播放
1/1