通常情况下,我们下载一个后端的二进制“文件流”,是需要如下
window.open('后端给你的URL')
其本质是打开一个“下载窗口”,然后使用传统的同步GET
请求去把我们想要的文件流下载下来。
但有时候,不同的业务需求,可能需要在导出数据时传入一些特殊的参数,且后端同事也不肯让步,就是要让你使用POST
请求去获取“文件流”,这时候,使用Ajax将是一个错误的决定,你通常在response里面会看到下面这种情况

会是一片乱码,这是因为ajax专门是为异步请求服务的,它不会帮你刷新页面,也不会帮你唤起“下载窗口”,ajax函数的返回类型只有xml、text、json、html等类型,没有“流”类型,所以我们要实现ajax下载,不能够使用相应的ajax函数进行文件下载。,所以不管你是使用的
GET
还是POST
,你都不能使用ajax做下载需求,我们一定要让请求是同步的,这样才能唤起下载窗口,对于GET
同步请求来说,方式就是上面的window.open()
形式,对于POST
请求,就要使用我们原始的form来传递参数。下面我提供一种JS原生写法的代码,来实现
POST
请求下载文件。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="renderer" content="webkit|ie-comp|ie-stand">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"/>
<meta http-equiv="Cache-Control" content="no-siteapp"/>
</head>
<body>
<input type="button" id="clickme" value="clickme" />
</body>
<script type="text/javascript">
function postExcelFile(params, url) { //params是post请求需要的参数,url是请求url地址
var form = document.createElement("form");
form.style.display = 'none';
form.action = url;
form.method = "post";
document.body.appendChild(form);
for(var key in params){
var input = document.createElement("input");
input.type = "hidden";
input.name = key;
input.value = params[key];
form.appendChild(input);
}
form.submit();
form.remove();
}
//点击导出按钮导出excel表格
clickme.onclick = function() {
var params = {};
params.queryDate='2018-08-16';
params.productId=0;
params.channel1Id='12924,12925,12926';
params.channel2Id='332584,12927,333950,314216';
postExcelFile(params, "http://wxs.ngrok.xiaomiqiu.cn/kpi/chnOperate/realTime/daily/list/export");
}
</script>
</html>
原生JS适用于任何JS项目,当然你也可以使用一些第三方的库(如Jquery)来生成DOM,获取DOM。
这里的主要思想就是在你进行下载操作的时候,创建一个隐藏的"表单"。将请求发出去以后,拿到“文件流”之后,再将其移除。
兼容性
我本人在使用这个方法的,IE(11)下回出现“下载页面”不能自动关闭的情况,我暂称其为bug吧,如果你不想这么做的话,那么可能就要再和后台同事协商一些换成GET
或者使用AJAXPOST
请求将参数传给后台,后台返回给你一个标志字符串,你再根据这个字符串进行GET
的window,open()
形式的下载,这都是要和后端同事多沟通了。
网友评论