PHP使用range协议实现输出文件断点续传代码实例
range协议用途:一般是用在断点续传的时候,但是实际的用户很大,例如你的webserver需要输出一个大文件,那么用range可以分段输出,缓解压力。同时在提供音乐视频等服务时可以缓冲下载,如果用户中途关闭,可以节约网络带宽。
<?php
//文件名
$filename=$_GET['filename'];
//文件路径
$location='media/'.$filename;
//后缀
$extension=substr(strrchr($filename,'.'),1);
if($extension=="mp3"){
$mimeType="audio/mpeg";
}elseif($extension=="ogg"){
$mimeType="audio/ogg";
}
if(!file_exists($location)){
header("HTTP/1.1404NotFound");
return;
}
$size=filesize($location);
$time=date('r',filemtime($location));
$fm=@fopen($location,'rb');
if(!$fm){
header("HTTP/1.1505Internalservererror");
return;
}
$begin=0;
$end=$size-1;
if(isset($_SERVER['HTTP_RANGE'])){
if(preg_match('/bytes=\h*(\d+)-(\d*)[\D.*]?/i',$_SERVER['HTTP_RANGE'],$matches)){
//读取文件,起始节点
$begin=intval($matches[1]);
//读取文件,结束节点
if(!empty($matches[2])){
$end=intval($matches[2]);
}
}
}
if(isset($_SERVER['HTTP_RANGE'])){
header('HTTP/1.1206PartialContent');
}else{
header('HTTP/1.1200OK');
}
header("Content-Type:$mimeType");
header('Cache-Control:public,must-revalidate,max-age=0');
header('Pragma:no-cache');
header('Accept-Ranges:bytes');
header('Content-Length:'.(($end-$begin)+1));
if(isset($_SERVER['HTTP_RANGE'])){
header("Content-Range:bytes$begin-$end/$size");
}
header("Content-Disposition:inline;filename=$filename");
header("Content-Transfer-Encoding:binary");
header("Last-Modified:$time");
$cur=$begin;
//定位指针
fseek($fm,$begin,0);
while(!feof($fm)&&$cur<=$end&&(connection_status()==0)){
printfread($fm,min(1024*16,($end-$cur)+1));
$cur+=1024*16;
}
range协议官方文档:http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html