使用javascript原生XHR下载流文件,可进行计时下载,当然也是可以通过from表单进行下载文件的,但页面可能会有跨域问题,索性就在PHP做个桥接处理了。
一、在页面添加一个按钮
<a href="javascript:;" class="btn btn-xs btn-primary btn-success btn-install" id="exportBtn" data-url="{:url('ajax/downloadExcel')}" >
<i class="fa fa-cloud-download"></i> 导出Excel
</a>
干嘛有那么麻烦,一个form
不就可以解决的事情,非要弄的怎么麻烦呢?原因是下载远程服务器文件,且与本项目不在同一服务器上。
二、xhr模拟表单下载
$('#exportBtn').on('click',function(){
let url= $(this).data('url')
let itime = 0;
$("#exportBtn").html(`正在下载,耗时<i style="color:red;font-size:16px;font-weight:700;padding: 0 5px;">${itime}</i>秒`);
let xhr = new XMLHttpRequest();
xhr.open('get', url, true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
xhr.responseType = 'blob';
xhr.send(null);
xhr.onload = function () {
if (this.status == 200) {
let blob = this.response;
let yLink = document.createElement('a');
let myDate = new Date();
let nowDateStr=Controller.dateFormat("YYYYmmddHHMMSS", myDate)
yLink.style.display = 'none';
let contentTypeHeader = xhr.getResponseHeader("Content-Type");
// 字符内容转变成blob地址
yLink.href = window.URL.createObjectURL(new Blob([blob], { type: contentTypeHeader }));
yLink.download = nowDateStr+'.xlsx';;
// 触发点击
document.body.appendChild(yLink);
yLink.click();
// 然后移除
document.body.removeChild(yLink);
clearTimeout(downloadTimer);
$("#exportBtn").html("<i class='fa fa-cloud-download'></i> 导出Excel");
$("#exportBtn").removeAttr("disabled");
}
}
let downloadTimer = setInterval(() => {
$("#exportExcel").children("i").text(++itime);
}, 1000);
})
三、通过PHP CURL 间接性下载流文件
/**
* 导出Excel
*/
public function downloadExcel(){
$url = 'http://XXX.XXX.XXX.XXX/api/export/excel';
$temp = [
'start_time'=>date("Y-m-d H:i:s",time())
];
$stremData = self::getWebFileStream($url,$temp,'post');
$t=time();
$today=date("YmdHis",$t);
$file_name= $today . '.xlsx';
$excelFile = $_SERVER['DOCUMENT_ROOT']."/excel-file/" . $file_name;
// 保存文件到指定路径
$ret=file_put_contents($excelFile,$stremData);
Log::info('====download方法中====当前系统时间======='.date("Y-m-d H:i:s",time()));
Log::info('>>>>>>>>>>>>>>>>>>>>>>>>>流文件>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>'.$ret);
// 释放文件内存
//unset($stremData);
self::output_for_download($excelFile, $file_name);
}
/**
* 获取网络接口里面的文件流
**/
protected function getWebFileStream($url,$params,$type){
$stream = "";
if(!isset($url) || empty($url))
return "";
$ch=curl_init();
if($type === "post"){
$temp = json_encode($params);
curl_setopt_array($ch,[
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_POST => 1,
CURLOPT_HEADER => 0,
CURLOPT_POSTFIELDS => $temp
]);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($temp))
);
}else{
curl_setopt_array($ch,[
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_HEADER => 0
]);
}
//输出结果
$stream = curl_exec($ch);
//推断curl请求是否超时
if(curl_errno($ch)){
$stream = file_get_contents($url);
}
//关闭
curl_close($ch);
return $stream;
}
/**
* 将文件输出到浏览器页面
*/
function output_for_download($filename, $title){
$fp = fopen($filename,"r");
header("Content-type: application/vnd.ms-excel;charset=gb2312");
header("Accept-Length: ".filesize($filename));
header("Content-Transfer-Encoding: binary");
header('Content-Disposition: attachment; filename="'.basename($filename).'"');
// 输出文件内容
while(!feof($fp)) {
echo fread($fp,filesize($filename));
}
fclose($fp);
unlink($filename); //删除文件
exit;
}