【场景描述】

微服务架构中,使用前后端分离设计,用户点击导出下载Excel列表,通过AJAX与后端SpringMVC交互获取下载文件,请求需要携带Authorization认证信息,并且需要考虑到IE浏览器的兼容问题

【解决方案】

Ajax下载文件的这种方式本来就是禁止的。出于安全因素的考虑,javascript是不能够保存文件到本地的,

所以ajax考虑到了这点,只是接受json,text,html,xml格式的返回值,二进制的返回格式就会抛出这个异常。ajax请求只是个“字符型”的请求,即请求的内容是以文本类型存放的。

文件的下载是以二进制形式进行的,虽然可以读取到返回的response,但只是读取而已,是无法执行的,js是无法调用到浏览器的下载处理机制和程序。

如果非要使用ajax的话,只能通过返回值得到生成的文件相关url。一个对文件生成流的处理url,这样操作来实现文件下载且页面无刷新。

后端返回二进制文件,前端通过 blob 数据格式接收,并通过构建a链接URL的方式实现文件的下载

【前端代码】

1:注意考虑IE浏览器的XMLHttpRequest兼容性问题
2:设置响应接收的类型为blob
3: 请求类型这里设置为json,是因为我在传输FormData时后端一直获取失败于是使用这种方式获取参数
4:AJAX请求头中添加Authorization认证Token
5:创建Blob接收后端返回的文件流对象
6:通过返回值得到生成的文件相关url
7:IE浏览器使用link.click();没反应,需要使用window.navigator.msSaveBlob(blob, downloadFileName);构建

function excelExport(url, params) {let xhr;if (window.XMLHttpRequest) {xhr = new XMLHttpRequest();} else {//IExhr = new ActiveXObject("Microsoft.XMLHTTP");}xhr.open('post', url);xhr.setRequestHeader('Content-Type', 'application/json;charset=utf-8')xhr.responseType = 'blob';xhr.setRequestHeader("Authorization", "Bearer " + localStorage.getItem("access_token"))xhr.send(JSON.stringify(params));xhr.onreadystatechange = function () {if (xhr.readyState === 4 && xhr.status === 200) {const blob = new Blob([xhr.response])let urlBlob = window.URL.createObjectURL(blob)//创建一个a标签元素,设置下载属性,点击下载let link = document.createElement('a')link.href = urlBloblink.style.display = 'none'//取出下载文件名const fileName = xhr.getResponseHeader('fileName')const downloadFileName = decodeURIComponent(fileName)link.setAttribute('download', downloadFileName);//IE浏览器if (window.navigator.msSaveBlob) {try {window.navigator.msSaveBlob(blob, downloadFileName);} catch (e) {console.log(e);}} else {link.click();}}}
}

参考的前端调用示例

function ebotMonitorExport() {let exportUrl = "/api-m/XXXX/XXXX/export";let searchVo = {code: $("#code").val(),name: $("#name").val()};excelExport(exportUrl, searchVo);
}

【后端代码】

后端就是一般的导出逻辑,返回文件流,唯一注意的就是需要返回的文件名称放在响应流头中
setResponseHeader(response, fileName);

  @PostMapping("/export")public void export(@RequestBody ExportVO vo, HttpServletResponse response) {service.export(vo, response);}
 //根据条件查询数据List<XXX> list = mapper.selectByExample(vo);//构建Excel头String[] title = {"XXX", "XXX", "XXX"};String[] fieldNames = {"code", "name", "createTime"};String filename = "数据列表" + DateUtil.getNowDateStr() + ".xls";String sheetName = "数据列表";ExcelUtil.writeExcel(list, title, fieldNames, "createTime", sheetName, response, filename);
    public static void writeExcel(List list, String[] title, String[] fieldNames, String toDateField, String sheetName,HttpServletResponse response, String fileName) {//创建HSSFWorkbookHSSFWorkbook wb = getWorkbookDetail(list, title, fieldNames, toDateField, sheetName, null, null);try {fileName = URLEncoder.encode(fileName, "UTF8");} catch (UnsupportedEncodingException e) {log.error(LogHandle.error(String.format("出现异常: %s", e.getMessage())).toString());}setResponseHeader(response, fileName);try (OutputStream os = response.getOutputStream()) {wb.write(os);} catch (IOException e) {log.error(LogHandle.error(String.format("出现异常: %s", e.getMessage())).toString());}}

前后端分离 AJAX 文件下载解决方案相关推荐

  1. 前后端分离Nginx部署解决方案

    前后端分离Nginx部署解决方案 转自:https://www.yuque.com/dukang-hfttn/mo27v1/po8zc3 一.获取前端代码编译发布步骤 获取FE前端源码 安装Nodej ...

  2. 前后端分离 ajax请求后台重定向

    最近在做的一个前后端分离的一个项目,这就涉及到登录验证的问题.我用的是token加上filter. 1,前端请求登录的时候,用用户名和加上当前时间生成一个token,存入redis,然后返回给前端. ...

  3. php拆分jsion_Php如何返回json数据,前后端分离的基本解决方案

    php返回json,xml,JSONP等格式的数据 返回json数据: header('Content-Type:application/json; charset=utf-8'); $arr = a ...

  4. 利用Nginx轻松实现Ajax的跨域请求(前后端分离开发调试必备神技)

    利用Nginx轻松实现浏览器中Ajax的跨域请求(前后端分离开发调试必备神技) 前言 为什么会出现跨域? 造成跨域问题的原因是因为浏览器受到同源策略的限制,也就是说js只能访问和操作自己域下的资源,不 ...

  5. pc网站调用微服务器,【微服务】前后端分离-跨域问题和解决方案

    跨域问题存在的原因 跨域问题的根本原因:因为浏览器收到同源策略的限制,当前域名的js只能读取同域下的窗口属性.什么叫做同源策略?就是不同的域名, 不同端口, 不同的协议不允许共享资源的,保障浏览器安全 ...

  6. 前后端分离与跨域的解决方案(CORS的原理)

    前后端分离 前后端分离的好处 最大的好处就是前端JS可以做很大部分的数据处理工作,对服务器的压力减小到最小. 后台错误不会直接反映到前台,错误接秒较为友好. 由于后台是很难去探知前台页面的分布情况,而 ...

  7. 前后端分离项目,跨域问题解决方案

    1.什么是跨域? 要了解跨域,先要说说同源策略. 同源策略是由 Netscape 公司提出的一个著名的安全策略,所有支持 JavaScript 的浏览器都会使用这个策略. 由于浏览器同源策略的限制,非 ...

  8. 014-Axios Ajax:前后端分离概述,发送json类型的参数,前后端分离开发:在线接口文档,前端工程化、Element、nginx

    第一节 Ajax概述 1.概述 概念: Asynchronous JavaScript And XML,异步的JavaScript和XML. 作用: 数据交换:通过Ajax可以给服务器发送请求,并获取 ...

  9. 前后端分离的跨域解决方案

    声明: 在以往的开发中,前后端分离也不是像现在这么热门,所谓的前端工程师也只不过是写好静态页面由Java工程师或者php工程师嵌入到页面中进行开发,这或许加重了这些工程师的工作量,而且在样式调试上由纯 ...

最新文章

  1. 离散型随机变量的分布律
  2. 使用Xcode和Instruments调试解决iOS内存泄露
  3. Boost:bind绑定和数据成员以及高级用途的测试程序
  4. 黄斑裂孔Macular Hole
  5. 数组的几种定义方式及初始化
  6. matlab2c使用c++实现matlab函数系列教程-floor函数
  7. 彻底删除文件(File Delete Absolutely) 最新3.01版本 也已经在中关村在线升级成功
  8. The eighteen day
  9. 第 7 章 Neutron - 075 - 为 Neutron 准备物理基础设施(I)
  10. C++刷屏器(DevCpp-5.10编译通过)
  11. 一堂难忘的计算机课作文,难忘的一节微机课_800字
  12. 17家中国初创IT公司的失败史【转】
  13. proxy 服务器配置
  14. 微信公众平台中业务域名,JS接口安全域名,网页授权域名配置的MP_verify_liCemlZVM1G3rJPy.txt文件放置位置
  15. guava LoadingCache 的用法
  16. Linux发行版:CentOS、Ubuntu、RedHat、Android、Tizen、MeeGo
  17. php 蓝奏网盘上传文件,教给大家一个蓝奏云高级玩法,如何把文件一键秒上传到蓝奏云网盘...
  18. rtx3050和rtx3050ti区别 rtx3050和rtx3050ti显卡什么水平
  19. 完全免费的OCR文字识别软件
  20. 【Java】将输入的 24 小时制时间转换为 12 小时制时间

热门文章

  1. django-ORM模型
  2. WiFi伴侣电脑版 v2.3.4 PC中文版
  3. 史上最全的深度学习面经总结(附答案详解)
  4. 计算机电缆 耐火,耐火计算机电缆型号
  5. 四川翌加:横拍和竖拍抖音短视频哪个更好
  6. HTML CSS JS 小总结
  7. 【Azure 学习】
  8. 如何做一个体贴的男友?(转自百度
  9. 创业路上教你怎样躲开创业陷阱
  10. 梁静茹成都开唱花样多 坐小火车藏礼盒中