建议查看最新版,以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请求下载文件。