PHP 实现断点续传的原理和方法
来源:互联网 发布:动物建模软件 编辑:程序博客网 时间:2024/05/29 18:41
PHP 实现断点续传的原理和方法
0. http协议从1.1开始支持静态获取文件的部分内容,为多线程下载和断点续传提供了技术支持。它通过在Header里两个参数实现的,客户端发请求时对应的是Accept-Range ,服务器端响应时对应的是 Content-Range。
1. 具体的请求和响应格式是这样: 资料来源 http://www.liqwei.com/network/protocol/2011/886.shtml
Range
用于请求头中,指定第一个字节的位置和最后一个字节的位置,一般格式:
Range:(unit=first byte pos)-[last byte pos]
Content-Range
用于响应头,指定整个实体中的一部分的插入位置,他也指示了整个实体的长度。在服务器向客户返回一个部分响应,它必须描述响应覆盖的范围和整个实体长度。一般格式:
Content-Range: bytes (unit first byte pos) - [last byte pos]/[entity legth]
一般正常回应
2. 问题及应对
有些虚拟机配置时它是不支持断点传输的,下载时不显示总大小和进度条,只能看到下载了多少,甚至是一直处于 0 ,直到下载完成,这在下载文件时很不爽;此外,服务器对 apk 文件类型没有指明是 Content-type: application/octet-stream ,造成火狐浏览器对安卓应用 apk 以文本方式输入,这是不是更不方便。
基于此,有必要通过 PHP 对这种特殊的情况作处理,方法是浏览器给这个 PHP 脚本发送 GET 请求下载文件,PHP 脚本给浏览器响应的 header 中包含 Content-Type: application/octet-stream 和 Content-Range: bytes 0-800/801 即可。同时须用 flush() 函数刷新浏览器的cache ,就能看到下载了多少,否则下载大小一直处于 0
3. 实例
既然思路有了,具体的代码或许很简单。我们只需处理服务端,无需理会客户端发了什么请求
4. 现成的函数 资料来源 http://www.cnblogs.com/lq527/p/6228577.html
5. Apache2 开启断点续传
在httpd.conf中尝试mod_headers: Header set Accept-Ranges bytes
#开启Accept-Ranges响应头
Lighttpd用户尝试在lighttpd.conf中进行下面的配置:
6. 资料参考
http断点续传原理:http头 Range、Content-Range http://www.liqwei.com/network/protocol/2011/886.shtml
HTTP Header里的Range和Content-Range参数 http://www.tuicool.com/articles/RBrMnen
php支持断点续传的文件下载类 http://www.tuicool.com/articles/eMr2Ufq
PHP实现HTTP断点续传的方法 http://www.cnblogs.com/lq527/p/6228577.html
HTTP状态码详解 http://tool.oschina.net/commons?type=5
0. http协议从1.1开始支持静态获取文件的部分内容,为多线程下载和断点续传提供了技术支持。它通过在Header里两个参数实现的,客户端发请求时对应的是Accept-Range ,服务器端响应时对应的是 Content-Range。
1. 具体的请求和响应格式是这样: 资料来源 http://www.liqwei.com/network/protocol/2011/886.shtml
Range
用于请求头中,指定第一个字节的位置和最后一个字节的位置,一般格式:
Range:(unit=first byte pos)-[last byte pos]
Content-Range
用于响应头,指定整个实体中的一部分的插入位置,他也指示了整个实体的长度。在服务器向客户返回一个部分响应,它必须描述响应覆盖的范围和整个实体长度。一般格式:
Content-Range: bytes (unit first byte pos) - [last byte pos]/[entity legth]
请求下载整个文件:
GET /test.rar HTTP/1.1 Connection: close Host: 116.1.219.219 Range: bytes=0-801 //一般请求下载整个文件是bytes=0- 或不用这个头
一般正常回应
HTTP/1.1 200 OK Content-Length: 801 Content-Type: application/octet-stream Content-Range: bytes 0-800/801 //801:文件总大小
2. 问题及应对
有些虚拟机配置时它是不支持断点传输的,下载时不显示总大小和进度条,只能看到下载了多少,甚至是一直处于 0 ,直到下载完成,这在下载文件时很不爽;此外,服务器对 apk 文件类型没有指明是 Content-type: application/octet-stream ,造成火狐浏览器对安卓应用 apk 以文本方式输入,这是不是更不方便。
基于此,有必要通过 PHP 对这种特殊的情况作处理,方法是浏览器给这个 PHP 脚本发送 GET 请求下载文件,PHP 脚本给浏览器响应的 header 中包含 Content-Type: application/octet-stream 和 Content-Range: bytes 0-800/801 即可。同时须用 flush() 函数刷新浏览器的cache ,就能看到下载了多少,否则下载大小一直处于 0
3. 实例
既然思路有了,具体的代码或许很简单。我们只需处理服务端,无需理会客户端发了什么请求
<?phpset_time_limit(0); // 这个必须有$filename = $_GET['appid']; // 接受的GET请求参数,其值为服务器上的文件if(file_exists($filename)) die("该文件不存在"); // 如果文件不存在,则终止脚本$fileinfo = pathinfo($filename); // 分析请求的值$size = filesize($filename); // 计算文件的大小$size2 = $size-1;header('Content-Range: bytes 0-' . $size2 . '/' . $size); // 返回内容范围,断点续传header('Content-Type: application/octet-stream'); // 文件类型强制为二进制#header('Content-Type: application/x-'.$fileinfo['extension']); // 或许这样也可以header('Content-Type: multipart/byteranges'); // 多段传输header('Content-Length: '. $size); // 文件的总大小// 提示用户保存,当 application/octet-stream 被使用时,任何类型的文件均被下载,不被浏览器打开。header('Content-Disposition: attachment; filename='.$fileinfo['basename']);flush(); // 刷新浏览器的cachereadfile($filename); // 读取文件exit(0);
4. 现成的函数 资料来源 http://www.cnblogs.com/lq527/p/6228577.html
修正了 header('Content-Type: application/octet-stream');
header('Accenpt-Ranges: bytes');
Content-Dispositon
<?php/** * PHP-HTTP断点续传实现 * @param string $path: 文件所在路径 * @param string $file: 文件名 * @return void */function download($path,$file) { $real = $path.'/'.$file; if(!file_exists($real)) { return false; } $size = filesize($real); $size2 = $size-1; $range = 0; if(isset($_SERVER['HTTP_RANGE'])) { //http_range表示请求一个实体/文件的一个部分,用这个实现多线程下载和断点续传! header('HTTP /1.1 206 Partial Content'); $range = str_replace('=','-',$_SERVER['HTTP_RANGE']); $range = explode('-',$range); $range = trim($range[1]); header('Content-Length:'.$size); header('Content-Range: bytes '.$range.'-'.$size2.'/'.$size); } else { header('Content-Length:'.$size); header('Content-Range: bytes 0-'.$size2.'/'.$size); } header('Accenpt-Ranges: bytes'); header('Content-Type: application/octet-stream'); header("Cache-control: public"); header("Pragma: public"); //解决在IE中下载时中文乱码问题 $ua = $_SERVER['HTTP_USER_AGENT']; if(preg_match('/MSIE/',$ua)) { //表示正在使用 Internet Explorer。 $ie_filename = str_replace('+','%20',urlencode($file)); header('Content-Disposition:attachment; filename='.$ie_filename); } else { header('Content-Disposition:attachment; filename='.$file); } $fp = fopen($real,'rb+'); fseek($fp,$range); //fseek:在打开的文件中定位,该函数把文件指针从当前位置向前或向后移动到新的位置,新位置从文件头开始以字节数度量。成功则返回 0;否则返回 -1。注意,移动到 EOF 之后的位置不会产生错误。 while(!feof($fp)) { //feof:检测是否已到达文件末尾 (eof) set_time_limit(0); //注释① print(fread($fp,1024)); //读取文件(可安全用于二进制文件,第二个参数:规定要读取的最大字节数) ob_flush(); //刷新PHP自身的缓冲区 flush(); //刷新缓冲区的内容(严格来讲, 这个只有在PHP做为apache的Module(handler或者filter)安装的时候, 才有实际作用. 它是刷新WebServer(可以认为特指apache)的缓冲区.) } fclose($fp);}
5. Apache2 开启断点续传
在httpd.conf中尝试mod_headers: Header set Accept-Ranges bytes
#开启Accept-Ranges响应头
<IfModule mod_headers.c> Header set Accept-Ranges bytes</IfModule>
Lighttpd用户尝试在lighttpd.conf中进行下面的配置:
## enabled for all file types##server.range-requests = "enable"## But, disable it for pdf files##$HTTP["url"] =~ "\.pdf$" { server.range-requests = "disable"}
6. 资料参考
http断点续传原理:http头 Range、Content-Range http://www.liqwei.com/network/protocol/2011/886.shtml
HTTP Header里的Range和Content-Range参数 http://www.tuicool.com/articles/RBrMnen
php支持断点续传的文件下载类 http://www.tuicool.com/articles/eMr2Ufq
PHP实现HTTP断点续传的方法 http://www.cnblogs.com/lq527/p/6228577.html
HTTP状态码详解 http://tool.oschina.net/commons?type=5
0 0
- PHP 实现断点续传的原理和方法
- 断点续传的原理和实现
- PHP断点续传的原理与实现
- PHP断点续传的原理与实现
- PHP实现HTTP断点续传下载的方法
- PHP实现HTTP断点续传的方法
- 断点续传的实现原理
- 断点续传的实现原理
- 从断点续传的原理来实现断点续传
- C# 断点续传原理和实现
- java实现断点续传的原理
- http协议学习-断点续传和多线程下载的实现原理
- ASP.NET实现断点续传的原理
- 多线程断点续传的原理及其简单实现
- Swift实现断点续传,Demo简单易懂,没有太多复杂模块和逻辑,完整体现断点续传的原理
- 断点续传原理与实现
- iOS- 断点续传实现原理
- 断点续传下载原理实现
- 网络攻防之——nmap工具的使用
- Intent详解
- CCF201509-2-日期计算
- Map 综述(一):彻头彻尾理解 HashMap
- codevs1001 舒适的路线 贪心枚举+并查集
- PHP 实现断点续传的原理和方法
- 盒子模型
- [第二类斯特林数 组合计数] 省选模拟赛 2 B. 两弹一星 missile
- 门面模式
- weblogic 和 tomcat 的区别利弊,摘自网友
- 如何用AltiumDesigner绘制STC89C51单片机原理图
- 安装office的ISO版本,虚拟光驱
- 初学二叉树
- 文章标题