php支持断点续传、分块下载的类
本文是为大家分享php支持断点续传、分块下载的类,供大家参考,具体内容如下
<?php
/**
*User:djunny
*Date:2016-04-29
*Time:17:18
*Mail:199962760@qq.com
*支持断点下载的类
*/
classdownloader{
/**
*downloadfiletolocalpath
*
*@param$url
*@param$save_file
*@paramint$speed
*@paramarray$headers
*@paramint$timeout
*@returnbool
*@throwsException
*/
staticfunctionget($url,$save_file,$speed=10240,$headers=array(),$timeout=10){
$url_info=self::parse_url($url);
if(!$url_info['host']){
thrownewException('UrlisInvalid');
}
//defaultheader
$def_headers=array(
'Accept'=>'*/*',
'User-Agent'=>'Mozilla/4.0(compatible;MSIE8.0;WindowsNT5.1;Trident/4.0)',
'Accept-Encoding'=>'gzip,deflate',
'Host'=>$url_info['host'],
'Connection'=>'Close',
'Accept-Language'=>'zh-cn',
);
//mergeheade
$headers=array_merge($def_headers,$headers);
//getcontentlength
$content_length=self::get_content_size($url_info['host'],$url_info['port'],$url_info['request'],$headers,$timeout);
//contentlengthnotexist
if(!$content_length){
thrownewException('Content-LengthisNotExists');
}
//getexistslength
$exists_length=is_file($save_file)?filesize($save_file):0;
//gettmpdatafile
$data_file=$save_file.'.data';
//gettmpdata
$exists_data=is_file($data_file)?json_decode(file_get_contents($data_file),1):array();
//checkfileisvalid
if($exists_length==$content_length){
$exists_data&&@unlink($data_file);
returntrue;
}
//checkfileisexpire
if($exists_data['length']!=$content_length||$exists_length>$content_length){
$exists_data=array(
'length'=>$content_length,
);
}
//writeexistsdata
file_put_contents($data_file,json_encode($exists_data));
try{
$download_status=self::download_content($url_info['host'],$url_info['port'],$url_info['request'],$save_file,$content_length,$exists_length,$speed,$headers,$timeout);
if($download_status){
@unlink($data_file);
}
}catch(Exception$e){
thrownewException($e->getMessage());
}
returntrue;
}
/**
*parseurl
*
*@param$url
*@returnbool|mixed
*/
staticfunctionparse_url($url){
$url_info=parse_url($url);
if(!$url_info['host']){
returnfalse;
}
$url_info['port']=$url_info['port']?$url_info['host']:80;
$url_info['request']=$url_info['path'].($url_info['query']?'?'.$url_info['query']:'');
return$url_info;
}
/**
*downloadcontentbychunk
*
*@param$host
*@param$port
*@param$url_path
*@param$headers
*@param$timeout
*/
staticfunctiondownload_content($host,$port,$url_path,$save_file,$content_length,$range_start,$speed,&$headers,$timeout){
$request=self::build_header('GET',$url_path,$headers,$range_start);
$fsocket=@fsockopen($host,$port,$errno,$errstr,$timeout);
stream_set_blocking($fsocket,TRUE);
stream_set_timeout($fsocket,$timeout);
fwrite($fsocket,$request);
$status=stream_get_meta_data($fsocket);
if($status['timed_out']){
thrownewException('SocketConnectTimeout');
}
$is_header_end=0;
$total_size=$range_start;
$file_fp=fopen($save_file,'a+');
while(!feof($fsocket)){
if(!$is_header_end){
$line=@fgets($fsocket);
if(in_array($line,array("\n","\r\n"))){
$is_header_end=1;
}
continue;
}
$resp=fread($fsocket,$speed);
$read_length=strlen($resp);
if($resp===false||$content_length<$total_size+$read_length){
fclose($fsocket);
fclose($file_fp);
thrownewException('SocketI/OErrorOrFileWasChanged');
}
$total_size+=$read_length;
fputs($file_fp,$resp);
//checkfileend
if($content_length==$total_size){
break;
}
sleep(1);
//fortest
//break;
}
fclose($fsocket);
fclose($file_fp);
returntrue;
}
/**
*getcontentlength
*
*@param$host
*@param$port
*@param$url_path
*@param$headers
*@param$timeout
*@returnint
*/
staticfunctionget_content_size($host,$port,$url_path,&$headers,$timeout){
$request=self::build_header('HEAD',$url_path,$headers);
$fsocket=@fsockopen($host,$port,$errno,$errstr,$timeout);
stream_set_blocking($fsocket,TRUE);
stream_set_timeout($fsocket,$timeout);
fwrite($fsocket,$request);
$status=stream_get_meta_data($fsocket);
$length=0;
if($status['timed_out']){
return0;
}
while(!feof($fsocket)){
$line=@fgets($fsocket);
if(in_array($line,array("\n","\r\n"))){
break;
}
$line=strtolower($line);
//getlocation
if(substr($line,0,9)=='location:'){
$location=trim(substr($line,9));
$url_info=self::parse_url($location);
if(!$url_info['host']){
return0;
}
fclose($fsocket);
returnself::get_content_size($url_info['host'],$url_info['port'],$url_info['request'],$headers,$timeout);
}
//getcontentlength
if(strpos($line,'content-length:')!==false){
list(,$length)=explode('content-length:',$line);
$length=(int)trim($length);
}
}
fclose($fsocket);
return$length;
}
/**
*buildheaderforsocket
*
*@param$action
*@param$url_path
*@param$headers
*@paramint$range_start
*@returnstring
*/
staticfunctionbuild_header($action,$url_path,&$headers,$range_start=-1){
$out=$action."{$url_path}HTTP/1.0\r\n";
foreach($headersas$hkey=>$hval){
$out.=$hkey.':'.$hval."\r\n";
}
if($range_start>-1){
$out.="Accept-Ranges:bytes\r\n";
$out.="Range:bytes={$range_start}-\r\n";
}
$out.="\r\n";
return$out;
}
}
#useage
/*
try{
if(downloader::get('http://dzs.aqtxt.com/files/11/23636/201604230358308081.rar','test.rar')){
//todo
echo'DownloadSucc';
}
}catch(Exception$e){
echo'DownloadFailed';
}
*/
?>
以上就是本文的全部内容,希望对大家的学习有所帮助。