1. 页面上下载文件,点击下载文件后页面无跳转
2. 下载按钮点击后disabled,文件可以下载后恢复可用
3. 后台准备文件可能会比较耗时,比如延迟2-5S,此时需要防止用户重复点击
4. 需要支持Chrome,IE浏览器
一开始采用的是js中window.location.href=path(或者window.open),这种方式写起来非常简单。但是因为后台直接是response的流输出,浏览器并不会刷新当前页面或者新打开一个窗口,这种情况下js代码无法监听后台数据何时真正的返回。故而想到了使用ajax的方式进行请求,监听到success后再恢复按钮可用。项目中使用了jquery,第一版代码如下:
//禁用按钮
$("#export").attr("disabled",false);
$.ajax({
type : "GET",
//请求的媒体类型
contentType : false,
processData : false,
//请求地址
url : "文件下载路径",
//请求成功
success : function(blob) {
//恢复按钮可用
$("#export").attr("disabled",true);
//处理数据
//如果是IE,使用msSaveOrOpenBlob
if (window.navigator.msSaveOrOpenBlob) {
navigator.msSaveOrOpenBlob(blob, fileName+'.xls');
}else{
//不是IE,模拟a的点击事件
var link=document.createElement("a");
link.href=URL.createObjectURL(blob);
link.style="visibility:hidden";
link.download=fileName+".xls";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
},
error : function(){
$("#export").attr("disabled",true);
alert("数据下载异常,请重试!");
}
});
数据返回后有两种处理方式,对非IE的浏览器而言,可以选择在document中新增一个隐藏的a标签,然后模拟click事件就可以下载了。而对IE而言,这个方法是不生效的。需要使用
navigator.msSaveOrOpenBlob(blob,fileName+'.xls')
以上代码进行测试,发现还是不行,处理到bolb数据的时候js会报错。这是因为jquery的ajax有封装,response的数据以字符串的方式解析了。此处下载的如果是doc,xls等文件肯定是不行的。其实应对也很简单,使用原生的XMLRequest对象进行处理即可。修改后的代码如下:
//禁用按钮
$("#export").attr("disabled",false);
//使用原生的ajax处理请求,blob存储response
var xhr=new XMLHttpRequest();
xhr.open('GET', url, true);
//禁用缓存,否则会出现xls文件不更新的bug
xhr.setRequestHeader("Cache-Control", "no-cache");
xhr.setRequestHeader("If-Modified-Since","0");
//指定返回类型,解决jquery的解析问题
xhr.responseType = "blob";
xhr.onload = function() {
//状态200,成功返回
if (this.status == 200) {
var blob = this.response;
//如果是IE,使用msSaveOrOpenBlob进行保存
if (window.navigator.msSaveOrOpenBlob) {
navigator.msSaveOrOpenBlob(blob, fileName+'.xls');
}else{
//不是IE,模拟a的点击事件
var link=document.createElement("a");
link.href=URL.createObjectURL(blob);
link.style="visibility:hidden";
link.download=fileName+".xls";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}else{
alert("数据下载异常,请重试!");
}
//恢复按钮可用
$("#export").attr("disabled",false);
}
xhr.send();
这里有几个注意的点:
好了,这是ajax实现异步下载的方法,赶紧试一试吧!