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