Web文件下载等待效果的实现[转]
原文:http://blog.csdn.net/accountwcx/article/details/46728563 作者:accountwcx
项目中需要实现导出Excel的功能,Excel不是保存在服务器上的文件,而是动态生成的。由于查询条件和数据大小的影响,生成Excel的时间不固定(大约5~10秒左右),因此需要做下载等待效果,防止用户多次点击下载。实现下载等待效果的关键是获取到后台导出Excel完成的时间或者捕获到Excel开始下载的事件。可以从两个方面入手,一个是在浏览器端触发onload事件。一个是在服务器端完成Excel导出,然后把Excel保存到服务器的临时位置,然后通知客户端去下载。
iframe实现下载等待#
用iframe实现下载等待的原理是把下载的路径给iframe的src,然后监听iframe的onload事件,当后台处理完成并返回文件时,会触发iframe的onload事件。使用该方法有两个问题:
- 参数通过url传递,如果url长度超过2048会被浏览器截断。
- iframe的onload事件在ie浏览器下触发不符合要求。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script type="text/javascript" src="http://cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
<span style="white-space:pre"> </span><script type="text/javascript" src="http://cdn.bootcss.com/jquery.blockUI/2.66.0-2013.10.09/jquery.blockUI.min.js"></script>
<title>文件下载等待</title>
</head>
<body>
<button id="btnDownload">文件下载</button>
<!--
下载的iframe
通过iframe的onload事件判断后台是否已经导出完成,浏览器是否开始下载
-->
<iframe id="iframeDownload" style="display:none;"></iframe>
<script type="text/javascript">
$(function(){
$('#iframeDownload').on('load', function(){
//当后台返回文件时,取消Loading。
$.unblockUI();
return false;
});
$('#btnDownload').click(function(){
var url = 'https://codeload.github.com/mugifly/jquery-simple-datetimepicker/legacy.zip/1.12.0';
download(url, '下载中,请稍候。。。');
return false;
});
});
/**
* 下载
* @param url {String} [必填]下载文件的路径,如果有参数,请通过url传值,如download.jsp?year=2015&month=7
* @param message {String} [可选]等待文字,默认是请稍候
*/
function download(url, message){
//如果message没有值或者不是字符串,使用默认等待文字。
if(!message || Object.prototype.toString.call(message) !== '[object String]'){
message = '请稍候。。。';
}
//显示等待效果
$.blockUI({
message: message
});
//让iframe的src调用url
$('#iframeDownload').attr('src', url);
}
</script>
</body>
</html>
上面的方法通过url传递参数,参数如果超过长度,则会被截断。可以通过form和iframe组合的方式解决,因为form通过post提交,不受参数大小的限制。具体思路是把需要提交的参数通过input放到form里面去,通过form的action动态指定下载文件的url,form的target指向iframe使得服务器的结果返回到iframe中,这样就能够触发iframe的onload事件。这个方法也存在ie下的兼容性问题。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script type="text/javascript" src="http://cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
<script type="text/javascript" src="http://cdn.bootcss.com/jquery.blockUI/2.66.0-2013.10.09/jquery.blockUI.min.js"></script>
<title>文件下载等待</title>
</head>
<body>
<button id="btnDownload">文件下载</button>
<!--
通过form提交参数,把服务器返回的结果在iframe中显示
-->
<form id="formDownload" method="post" target="downloadTarget" style="display:none;">
<iframe id="iframeDownload" name="downloadTarget"></iframe>
<div class="form-params">
<!-- 提交到后台的参数,如果有多个参数,可以用多个hidden -->
<input type="hidden" name="param" value="" />
</div>
</form>
<script type="text/javascript">
$(function(){
$('#iframeDownload').on('load', function(){
//当后台返回文件时,取消Loading。
$.unblockUI();
return false;
});
$('#btnDownload').click(function(){
var url = 'https://codeload.github.com/mugifly/jquery-simple-datetimepicker/legacy.zip/1.12.0';
download(url, [
{
name: 'time',
value: new Date().getTime()
},
{
name: 'year',
value: new Date().getFullYear()
}
], '下载中,请稍候。。。');
return false;
});
});
/**
* 下载
* @param url {String} [必填]下载文件的路径
* @param params {Object} [可选]提交到后台的参数,如[{name:'year',value:2015},{name:'month',value:7}]
* @param message {String} [可选]等待文字,默认是请稍候
*/
function download(url, params, message){
//如果message没有值或者不是字符串,使用默认等待文字。
if(!message || Object.prototype.toString.call(message) !== '[object String]'){
message = '请稍候。。。';
}
//显示等待效果
$.blockUI({
message: message
});
var $form = $('#formDownload');
//更换form的请求路径
$form.attr('action', url);
//把form下的全部参数去掉
$form.children('.form-params').remove();
var k, $params, $input;
if(Object.prototype.toString.call(params) === '[object Array]'){
//把新的参数添加到form下以便提交
$params = $('<div class="form-params"></div>');
$form.append($params);
$.each(params, function(i, v){
//创建隐藏的input
$input = $('<input type="hidden" name="' + v.name + '" />');
$input.val(v.value);
$params.append($input);
});
}
//提交请求
$form.submit();
}
</script>
</body>
</html>