版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_29673403/article/details/77962026
最近做项目的时候就遇到需要把用户分散在多个数据表中的数据整合到一起既可以在线查看,又能导出excel。对于这个需求,如果用户量小的情况下直接点击链接跳转请求服务器处理从数据表中取出数据生成excel再返回客户端进行打开下载操作即可。但是当用户非常多,数据非常大的时候服务器处理请求的所需要的时间就会越长,当超出客户端获取响应的等待时间就会返回“502 Bad GateWay”这样的超时反馈。这显然不是我们想要。那么我们需要在处理数据的过程中持续给客户端反馈,以避免出现超时连接的情况。这时候就考虑用ajax异步处理数据读取过程,然后再通过window.location.href=regionURL;
来访问文件下载链接进行excel下载。(注意:ajax请求只是个“字符型”的请求,即请求的内容是以文本类型存放的。文件的下载是以二进制形式进行的,所以ajax无法处理二进制流的response来下载文件)
首先我们来看后台代码实现:
if ($_GET['exporttype'] == 'excel'){
if(!isset($_GET['id']) && !isset($_GET['end']))//id是指用户表的id,用来定位最后一个取出的数据,以此为标准取下一个1000条数据
return false;
if(isset($_GET['end'])){//end表示数据已经全部准备完毕可以下载excel
import('libraries.excel');
$excel_obj = new Excel();
$excel_data = $_SESSION['excel_data'];
//设置样式
$excel_obj->setStyle(array('id'=>'s_title','Font'=>array('FontName'=>'宋体','Size'=>'12','Bold'=>'1')));
$excel_data = $excel_obj->charset($excel_data,CHARSET);
$excel_obj->addArray($excel_data);
$excel_obj->addWorksheet($excel_obj->charset('table1',CHARSET));
$file_name = $excel_obj->charset('用户行为数据统计',CHARSET).date('Y-m-d-H',time());
$excel_obj->generateXML($file_name);//生成excel文件,并使用header()函数来将它交付给浏览器。
unset ($_SESSION['excel_data']);return;//销毁session
}
//导出Excel
if($_GET['id'] == 0){
$excel_data = array();
//header
foreach ($statlist['headertitle'] as $v){
$excel_data[0][] = array('styleid'=>'s_title','data'=>$v);//设置表头
}
Session_start();
$_SESSION['excel_data']=$excel_data;//用session存储取出的数据,防止ajax请求的时候把上一次请求的数据刷新掉
}else{
$excel_data = $_SESSION['excel_data'];
}
//data
$data = $model->getUserDataList($_GET['id'], 1000);
if(!empty($data)){
$pagenum = 1000*$_GET['page'];
foreach ($data as $k=>$v){
$k = $pagenum + $k;
$excel_data[$k+1][] = array('data'=>$v['user']);
$excel_data[$k+1][] = array('data'=>$v['phone']);
$excel_data[$k+1][] = array('data'=>$v['contacts']);
$excel_data[$k+1][] = array('data'=>$v['email']);
$excel_data[$k+1][] = array('data'=>$v['wechat_no']);
$excel_data[$k+1][] = array('data'=>$v['is_bind']);
$excel_data[$k+1][] = array('data'=>$this->getAreaInfo($v['area_id']));//所在地
$excel_data[$k+1][] = array('data'=>$this->getIndustryInfoList($v['id']));//行业方向
$excel_data[$k+1][] = array('data'=>$this->getTagInfoList($v['id']));//技术方向
$excel_data[$k+1][] = array('data'=>$v['login_number']);
$excel_data[$k+1][] = array('data'=>$v['pc_login']);
$excel_data[$k+1][] = array('data'=>$v['wx_login']);
$excel_data[$k+1][] = array('data'=>date('Y-m-d-H', $v['last_time']));
$excel_data[$k+1][] = array('data'=>date('Y-m-d-H', $v['time']));
$excel_data[$k+1][] = array('data'=>$v['user_authentication_type']);
$excel_data[$k+1][] = array('data'=>$v['enterprise_name']);
$excel_data[$k+1][] = array('data'=>$v['is_store']);
$excel_data[$k+1][] = array('data'=>$v['title']);
$excel_data[$k+1][] = array('data'=>$v['need_count']);
$excel_data[$k+1][] = array('data'=>$v['t_count']);
$excel_data[$k+1][] = array('data'=>$v['goods_count']);
}
$last = array_pop($data);
$id = $last['id'];
$_SESSION['excel_data']=$excel_data;
die(json_encode(array('id'=>$id,'msg'=>$excel_data)));
}else{
die(json_encode(array('msg'=>'success')));
}
}
前台Ajax代码
<a class="btns" href="javascript:void(0);" id="export_btn"><span>导出Excel</span></a>
<script>
$(function () {
//导出图表
$("#export_btn").click(function(){
ajaxFile();
});
});
function ajaxFile(id,page){
var id = arguments[0] ? arguments[0] : 0;
var page = arguments[1] ? arguments[1] : 0;
$.ajax({
url: "<?php echo $output['actionurl'];?>&exporttype=excel",
type: 'GET',
data: {
id:id,
page:page,
},
dataType:"json",
success: function(obj){
if(obj){
if(obj.msg == "success"){
window.location.href="<?php echo $output['actionurl'];?>&exporttype=excel&end=1";
}else{
ajaxFile(obj.id, ++page);
}
}else{
alert("ERROR!");
}
}
})
}
</script>
最后展示generateXML()方法是如何生成excel文件,并使用header()函数来将它交付给浏览器。
/**
* 生成excel文件
* 最后生成excel文件,并使用header()函数来将它交付给浏览器。
* @param string $filename 文件名称
*/
public function generateXML ($filename)
{
$encoded_filename = urlencode($filename);
$encoded_filename = str_replace("+", "%20", $encoded_filename);
//头
$ua = $_SERVER["HTTP_USER_AGENT"];
header("Content-Type: application/vnd.ms-excel");
if(preg_match("/MSIE/", $ua)){
header('Content-Disposition: attachment; filename="'.$encoded_filename.'.xls"');
}else if(preg_match("/Firefox/", $ua)){
header('Content-Disposition: attachment; filename*="utf8\'\''.$filename.'.xls"');
}else{
header('Content-Disposition: attachment; filename="'.$filename.'.xls"');
}
header('Cache-Control: max-age=0');
echo stripslashes ($this->header);
//样式
echo "\n<Styles>";
foreach((array)$this->cellstyle as $k=>$v){
echo "\n".$v;
}
echo "\n</Styles>";
//工作表
echo implode ("\n", $this->worksheets);
echo $this->footer;
}
至此,就实现了使用ajax异步导出数据到excel的全部内容。我当时做的时候也是犯了“ajax不能下载文件”的错误(为什么不能下载呢,据百度解释是由前端JS来操作处理IO流具有很大的安全隐患),将所有的请求都交由ajax去执行,导致执行到下载excel那一步就报错了。调试了一下午,才搞明白这个问题所在,实在是印象深刻,所以决定记下来,留待以后参考。有不同想法的小伙伴也可以跟我来交流呀,共同学习进步~~