建议查看最新版,以JSON格式传输数据,下文是根据表单形式提交数据,内容格式在传输可能会异常。 表单内容提交的形式只推荐传输简单的数据类型,即v=x&c=t;这种。对于List等数据,推荐使用上文链接的内容,因为form表单会将list数据以,形式隔开,将list数据以字符串形式拼接并赋值给x。但是后台会遇到有时接收不到参数的情况。
今天遇到了个需求,要求客户端发送文件后,经过服务器处理后再返回给客户端。一开始想着GET和POST的主要区别是传输数据方式不同,对于文件接收应该不受影响,结果试了下直接通过AJAX POST请求能够传输文件,但是接收不了文件。
在网上看了下,用AJAX的POST请求接收文件,得以BLOB流的形式规定响应格式。具体如下:
$('#template',container).click(function () {
$.ajax( {
headers:{"Content-Type": "application/json"},
url:'',
type:'post',
success:function(data,state,response){
var fileName = response.getResponseHeader("Content-Disposition").split(";")[1].split("=")[1].split(".xlsx")[0]; // 根据接口返回情况拿到文件名
var blob = new Blob([data], { type: "application/octet-stream" }); // 通过返回的流数据 手动构建blob 流
var reader = new FileReader();
reader.readAsDataURL(blob); // 转换为base64
reader.onload = function (e) { // 转换完成,创建一个a标签用于下载
var a = document.createElement("a");
console.log(decodeURIComponent(fileName));
a.download = decodeURIComponent(fileName) + ".xlsx"; // 构建 下载的文件名称以及下载的文件格式(可通过传值输入)
if (typeof e.target.result === "string") {
a.href = e.target.result;
}
a.click();
};
}
});
根据打印日志,可以看到能正确拿到文件名,但是返回的数据乱码,服务器设置响应内容类型也无效,客户端设置响应内容类型也失效,于是只能寻求其他方法,决定使用原生JS实现。代码如下
if (res.RESULT.length > 0) {
var xhr = new XMLHttpRequest();
//url改成post请求地址
xhr.open('POST', url, true);
xhr.setRequestHeader("Content-Type", 'application/x-www-form-urlencoded');
//POST传参内容,后端要用request.getParameter接收
//我传输的是List类型,getParameter接收的是String
//服务端根据需求转换成List。
xhr.send("list="+res.RESULT);
xhr.responseType = 'blob';
xhr.onload = function (e) {
if (this.status == 200) {
var blob = this.response;
var a = document.createElement('a');
var url = window.URL.createObjectURL(blob);
a.href = url;
//获取后端文件名称
var fileName = decodeURI(xhr.getResponseHeader('content-disposition'));
console.log(fileName)
//截取=字符串后面的内容
var str = fileName.match(/=(\S*)/)[1];
console.log(str)
a.download = str;
a.click();
window.URL.revokeObjectURL(url);
}
}
}
服务器端接收数据
public void failedDataExport(HttpServletRequest request, HttpServletResponse response,ModelMap modelMap) throws Exception{
//接收前端传来的list数据
String tmp = request.getParameter("list");
//根据业务处理tmp,转换为想要的数据。由于我传来的是List,转成String会变成xx,xxx。再根据tmp.split(",")还原,具体情况具体实现。
}
最后成功下载成功文件。如果是用axios的项目,推荐使用axios进行post请求下载文件。axios方法POST请求下载。
最后提供下思路,如果不想通过以上方法实现,可以上传完文件后服务器处理,返回个a链接,里面包含服务器生成的文件名,用户通过点击a链接生成GET请求下载文件,或者通过JS再生成个GET请求下载文件。