下载大量数据到Excel表格时,无法查看下载的实时进度。
效果展示:
1、统计数据数量:
2、显示数量:
3、下载进度条展示:
代码:
1、前端显示代码
<link rel="stylesheet" href="__PUBLIC__/javascripts/admin/artdialog/skins/default.css" type="text/css"/>
<script type="text/javascript" src="__PUBLIC__/javascripts/admin/jquery-1.7.2.min.js"></script>
<script rel="stylesheet" src="__PUBLIC__/javascripts/admin/artdialog/jquery.artDialog.js"></script>
<script rel="stylesheet" src="__PUBLIC__/javascripts/admin/artdialog/plugins/iframeTools.source.js"></script>
<div class="content-search">
<form action="{:U('/Sale/ImportB2bHistory/downloadOrders')}" method="get" class="form-inline" id="downloadOrders" target="_blank">
<div class="control-group">
<label class="control-label">发货日期
<input type="datetime" placeholder="起始日期" name="begin_time" value="{$condition.begin_time}" id="begin_time"
onClick="WdatePicker({dateFmt:'yyyy-MM-dd'})"
class="Wdate"/>
</label>
<label class="control-label">发货日期
<input type="datetime" placeholder="结束日期" name="end_time" value="{$condition.end_time}" id="end_time"
onClick="WdatePicker({dateFmt:'yyyy-MM-dd'})"
class="Wdate"/>
</label>
</div>
<div>
<button style="margin-right: 10%" class="btn btn-primary" type="button" onclick="processBar()">
<i class="icon-download icon-white"></i> 导出
</button>
</div>
</form>
</div>
<script type="text/javascript" language="javascript">
var search_uri = "{:U('downloadOrders')}";// 请求地址
var process_uri = "{:U('getProcess')}";// 请求地址
var win = window.top; // 顶层页面window对象
var processBar2 ;
// processBar函数如下
function processBar() {
tip();// 弹出统计总数对话框
doRequest();
}
function doRequest() {
var begin_time = $("#begin_time").val();
var end_time = $("#end_time").val();
//ajax请求总数
$.post(search_uri, {begin_time: begin_time, end_time: end_time}, function (json) {
var return_arr = jQuery.parseJSON(json);
var num = return_arr.total;// 任务总数
var processnum = return_arr.processnum;// 当前数
if (num == 0) {
poptip.title('系统消息');
poptip.content('查询结果为空,不能进行数据导出');
} else {
poptip.close();// 关闭提示框
doConfirm(num, processnum);// 弹出确认下载交互界面
}
});
}
// 弹出确认下载
function doConfirm(num, processnum) {
var msg = '总有 <span style="color: red">' + num
+ '</span> 行,可能会时间较长。<br />您还需要继续吗?';
var content = '<progress max="100" value="0" id="processbar" style="text-align: center;width: 300px;"></progress><br/>' +
'<span id="progress_info"></span>';
// 提示是否继续
art.dialog.confirm(msg, function () {
// 弹出进度条
showProcess = art.dialog.through({
title: '数据导出进度',
content: content,
lock: true,
width: 350,
opacity: '.1',
button: [
{
name: '取消',
callback: function () {
window.location.reload();
}
}
]
});
showProcess.show();
win.$('#processbar').val(processnum * 100 / num);
win.$('#progress_info').show().text('正在导出,请等待,请勿关闭窗口...');//当继续的时候
$.ajax({
url:"{:U('doDownloadOrders')}",
type:"post",
async:true,
error:function (data) {
alert("下载失败!");
},
success:function (data) {
clearInterval(processBar2);// 关闭自动定时执行
showProcess.close();
window.location.href = data;
}
});
processBar2 = setInterval(sync_process, 1000);// 每隔1秒执行一次
});
}
// 获取进度
function sync_process() {
$.ajax({
url:process_uri,
type:"post",
async:true,
success:function (json) {
var return_arr = jQuery.parseJSON(json);
var num = return_arr.total;// 任务总数
var processnum = return_arr.processnum;// 当前数
update_process(num, processnum);
}
});
}
/* 更新进度条 */
function update_process(num, processnum) {
win.$('#processbar').val(processnum * 100 / num);
}
</script>
2、服务器代码
/**
* 导出客户订单下载
*/
public function downloadOrders(){
// 查询条件
$condition = I('POST.',null,'trim');
$datas = $this->getDatas($condition);
S('PROCESS_DOWNLOAD_DATA',$datas,60);// 缓存数据
S('PROCESS_DOWNLOAD_TOTAL',count($datas),60);
S('PROCESS_DOWNLOAD_PROCESSNUM',0);
$re_arr = array(
'total' => count($datas),
'processnum' => 0,
);
echo json_encode($re_arr);
exit;
}
/**
* 获取进度条的执行进度数据
*/
public function getProcess(){
$re_arr = array(
'total' => S('PROCESS_DOWNLOAD_TOTAL'),
'processnum' => S('PROCESS_DOWNLOAD_PROCESSNUM')
);
echo json_encode($re_arr);
exit;
}
/**
* 生成要下载的文件
*/
public function doDownloadOrders(){
$path = 'Cache/Runtime/Admin/downloads/';
if (!is_dir($path)) {
@mkdir($path, 0777, true);
}
set_time_limit(0);
session_write_close();// 断开AJAX请求,无需等待响应
$datas = S('PROCESS_DOWNLOAD_DATA');
// 设置表头字段并指定展示顺序
$firstLine = array('A','B','C');
import("Org.Excel.PHPExcel");// 导入扩展类
$objPHPExcel = new \PHPExcel();// 实例化类
$objPHPExcel->getProperties()
->setCreator("123")
->setLastModifiedBy("123")
->setTitle("Office 2003 XLSX Test Document")
->setSubject("Office 2003 XLSX Test Document")
->setDescription("Test document for Office 2003 XLSX, generated using PHP classes.")
->setKeywords("office 2003 openxml php")
->setCategory("Test result file");
$objActSheet = $objPHPExcel->setActiveSheetIndex(0);// 设置当前的sheet
// EXCEL表头
if($firstLine){
$r = 'A';
foreach($firstLine as $v){
$objActSheet->setCellValue($r.'1',$v);
$r ++;
}
}
$i = 2;
foreach($datas as $value)
{
$r = 'A';
foreach($value as $value2)
{
if($r == 'B' || $r == 'P' || $r == 'Q'){
$objActSheet->setCellValueExplicit($r.$i, $value2, \PHPExcel_Cell_DataType::TYPE_STRING);
}else{
$objActSheet->setCellValue($r.$i, $value2);
}
$r++;
}
$i++;
S('PROCESS_DOWNLOAD_PROCESSNUM',$i-2);// 更新缓存的进度
}
$filename = 'Orders'.date('YmdHis') . '.xls';
$objPHPExcel->getActiveSheet()->setTitle('工作表1');// sheet标题
$objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
$objWriter->save($path.$filename);
echo '/'.$path.$filename; // $_SERVER['HTTP_HOST'].'/'.$path.$filename;
exit;
}
JS发起请求后必须等待服务器返回结果才向下执行,才会解析后面请求的结果,这样导致下载数据到Excel文件中时不能再次发起请求读取下载进度。
在此session_write_close()函数端口AJAX请求,无需等待服务器返回结果,向下执行,该请求会正常执行完毕。
session_write_close();// 断开AJAX请求,无需等待响应