场景背景
1.一般来说,都是使用get请求后台接口,如此后台返回文件流于浏览器,则可直接下载。
2.那么除一般情况,就有特殊情况,比如你的请求接口参数特别长,此时便不可使用get请求,get请求的参数长度是有限的。那么就使用到本文的解决方案。
废话不多说,直接撸代码!!!
一 JAVA后台接口示例
/*** 下载文件** @param request request请求对象* @param response response相应对象* @param userVO 请求参数-接收前端formData对象*/@RequestMapping("/download")@ResponseBodypublic void downloadFile(HttpServletRequest request, HttpServletResponse response, UserVO userVO) throws IOException {//得到要下载的文件名String fileName = request.getParameter("filename");fileName = new String(fileName.getBytes("iso8859-1"), StandardCharsets.UTF_8);//上传的文件都是保存在/WEB-INF/upload目录下的子目录当中String fileSaveRootPath = request.getServletContext().getRealPath("/WEB-INF/upload");//通过文件名找出文件的所在目录String path = findFileSavePathByFileName(fileName, fileSaveRootPath);//得到要下载的文件File file = new File(path + "\\" + fileName);//如果文件不存在if (!file.exists()) {request.setAttribute("message", "您要下载的资源已被删除!!");return;}//处理文件名String realName = fileName.substring(fileName.indexOf("_") + 1);//设置响应头,控制浏览器下载该文件,此处的文件名要进行编码处理否则前端显示会乱码response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(realName, String.valueOf(StandardCharsets.UTF_8)));try (//读取要下载的文件,保存到文件输入流FileInputStream in = new FileInputStream(path + "\\" + fileName);//创建输出流OutputStream out = response.getOutputStream()) {//创建缓冲区byte[] buffer = new byte[1024];int len = 0;//循环将输入流中的内容读取到缓冲区当中while ((len = in.read(buffer)) > 0) {//输出缓冲区的内容到浏览器,实现文件下载out.write(buffer, 0, len);}} catch (IOException e) {throw new RuntimeException(e);}}
二 前端代码示例
function exportFn() {var userVO = new FormData();userVO.append('id', id)userVO.append('name', name)ax({method: 'post',url: baseUrl+"/download"),data: userVO,//重要:相应类型必须为blobresponseType: 'blob'}).then(function (res) {var contentDisposition = decodeURI(res.headers["content-disposition"]);var fileRegex = /([^(filename=)]+\.xlsx?)$/g;var result = contentDisposition.match(fileRegex);var fileName = '检查率统计.xlsx';if (result.length > 0) {fileName = result[0]}var blob = new Blob([res.data]);var url = window.URL.createObjectURL(blob); // 创建 url 并指向 blobvar a = document.createElement('a');a.href = url;a.download = fileName;a.click();window.URL.revokeObjectURL(url); // 释放该 url$("input[name=CSRFTid]").hide()});
}
注意事项:
一 后台文件名需要进行编码操作
//设置响应头,控制浏览器下载该文件,此处的文件名要进行编码处理否则前端显示会乱码
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(realName, String.valueOf(StandardCharsets.UTF_8)));
二 前端文件名称进行解码操作
//从header中获取到包含文件名的信息进行解码操作
var contentDisposition = decodeURI(res.headers["content-disposition"]);
三 前端获取文件名
//从header中取得包含文件名的信息并进行解码
var contentDisposition = decodeURI(res.headers["content-disposition"]);
//匹配文件名的正则
var fileRegex = /([^(filename=)]+\.xlsx?)$/g;
var result = contentDisposition.match(fileRegex);
var fileName = '检查率统计.xlsx';
//取得文件名并赋值
if (result.length > 0) {fileName = result[0]
}
后语:
至此,大功告成!!!