流程是浏览器访问A接口 A代理B接口 B生成下载文件并触发浏览器下载
B返回给A的是一个文件流 如下图

A代理分块下载
//参数说明:
//file_dir:文件所在目录
//file_name:文件名
function download($file_dir,$file_name){
//获取文件大小
$file_size = 0;
$fileArr = get_headers($file_dir);
foreach ($fileArr as $k=>$v){
$arr = explode("Content-Length: ", $v);
if(!empty($arr[1])){
$file_size = $arr[1];
break;
}
}
if(empty($file_size)){
return false;
}
header("Content-type: application/octet-stream");
header("Accept-Ranges: bytes");
header("Accept-Length: $file_size");
header("Content-Disposition: attachment; filename=".$file_name);
$fp = fopen($file_dir,"r");
$buffer_size = 1024;
$cur_pos = 0;
while(!feof($fp)&&$file_size-$cur_pos>$buffer_size){
$buffer = fread($fp,$buffer_size);
echo $buffer;
$cur_pos += $buffer_size;
}
$buffer = fread($fp,$file_size-$cur_pos);
echo $buffer;
fclose($fp);
return true;
}
$parame["id"] = intval(Yii::$app->request->get('id', 0));
$zipName = $parame["gameId"] .'.zip';
$parame=http_build_query($parame);
$this->download($this->pincheApiUrl."/userinfo/download?". $parame, $zipName);
/**
* 代理下载
* @param unknown $file_dir 文件所在目录/文件流
* @param unknown $file_name 生成文件名
* @return boolean
*/
function download($file_dir,$file_name){
try {
$fp = fopen($file_dir,"r");
$buffer_size = 1024;
//读第一次,判断是否生成文件成功
$buffer = fread($fp,$buffer_size);
if($buffer == "无法找到文件!" || $buffer =="无法打开文件,或者文件创建失败"){
echo $buffer;die;
}
header("Content-type: application/octet-stream");
header("Accept-Ranges: bytes");
header("Content-Disposition: attachment; filename=".$file_name);
echo $buffer;
while(!feof($fp)){
$buffer = fread($fp,$buffer_size);
echo $buffer;
}
fclose($fp);
return true;
}catch (\Exception $e) {
// print $e->getMessage();
echo "失败";
exit();
}
}
==================================CURL==================================
目前有一个接口 A http://192.168.137.73/test2.php
$localFileName = "123.zip";
$fp = fopen($localFileName,"r");
$buffer_size = 1024;
// var_dump($_SERVER);die;
//读第一次,判断是否生成文件成功
$buffer = fread($fp,$buffer_size);
if($buffer == "无法找到文件!" || $buffer =="无法打开文件,或者文件创建失败"){
echo $buffer;die;
}
header("Content-type: application/octet-stream");
header("Accept-Ranges: bytes");
header("Content-Disposition: attachment; filename=".$localFileName);
echo $buffer;
while(!feof($fp)){
$buffer = fread($fp,$buffer_size);
echo $buffer;
}
fclose($fp);
现在需要curl 请求这个接口实现代理下载, 分段接收
public static function curlDownload($url, $params,$method = "GET",$header = array(),$cookie="") {
$ch = curl_init();
//下载一个超过1G的大文件
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/binary","Expect:") );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
switch ($method){
case "GET":
if (! empty($params)) {
$url = $url . (strpos($url, '?') ? '&' : '?') . (is_array($params) ? http_build_query($params) : $params);
}
curl_setopt($ch, CURLOPT_URL, $url);
break;
case "POST":
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
curl_setopt($ch, CURLOPT_URL, $url);
break;
}
if(!empty($header)){
curl_setopt ( $ch, CURLOPT_HTTPHEADER, $header );
}
if(!empty($cookie)){
curl_setopt($ch, CURLOPT_COOKIE, $cookie);
}
//分段返回header
curl_setopt($ch, CURLOPT_HEADERFUNCTION, function ($ch, $string){
$length = strlen($string);
$arr = explode("Content-Disposition: attachment; filename=", $string);
if(!empty($arr) && !empty($arr[1])){
header('Cache-Control: public');
header('Content-Description: File Transfer');
header('Content-Transfer-Encoding: binary'); //告诉浏览器,这是二进制文件
header("Content-Disposition: attachment; filename=$arr[1]");
}
// echo "Header: $string<br />\n";
return $length;
});
//分段缓存
curl_setopt($ch, CURLOPT_BUFFERSIZE, 2048);
//分段返回body 和长度
curl_setopt($ch, CURLOPT_WRITEFUNCTION, function ($ch, $string){
$length = strlen($string);
echo $string;
// echo "Received $length bytes<br />\n";
return $length;
});
curl_exec($ch);
if ($error = curl_error($ch)) {
echo "Error: $error<br />\n";
}
}
声明:此文系舞林cuzn(www.wulinlw.org)原创稿件,转载请保留版权