如何应对POST方式下载文件的接口
jQuery的下载,需要承载一个插件去做
今天遇到一个问题,后台给的接口由于需要前端传入过多的参数,只能接受用post去下载文件。
正常情况下第一反应是用xhr
对象去发送post
请求,结果并没有触发浏览器的下载。
看了一下responseHeader
里已经设置了content-dispositon:attachment
,但是返回的流媒体会存在于接口返回的Response中。
试着window.open(URL.createObjectURL(new Blob(res)))
,只是inline的形式打开了这个文件,并没有触发浏览器下载行为。
最后发现,其实不是header
的问题,问题是AJAX
并不会唤起浏览器的下载窗口,AJAX
设计的初衷就是用来实现异步刷新的,用以改善原始的form表单提交刷新页面的问题。具体的官方证据暂时还没找到,只有stackoverflow。
所以选择有以下:
1.说服后端使用get方式。
get的请求方式可以用window.open(url,'_self');配置使用
- 不适用
AJAX
,创建一个隐形的表单来提交,设置form
的target
为_blank
来弹出下载对话框(推荐使用)。 - 如果是get请求也不建议直接使用
AJAX
去请求,否则传回来的流还是需要处理,建议使用隐形的a标签 - URL.createObjectURL(new Blob(res),利用前端H5提供的a的
download
属性来下载。IE11都不兼容。 - IE10、IE11有一个方法
window.navigator.msSaveBlob
可以将File或Blob对象保存到本地磁盘。 - 最坏的打算就是拿到那些流,转换为base64,可以直接放入a标签的href
function download() { var url = 'download/?filename=aaa.txt'; var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); // 也可以使用POST方式,根据接口 xhr.responseType = "blob"; // 返回类型blob // 定义请求完成的处理函数,请求前也可以增加加载框/禁用下载按钮逻辑 xhr.onload = function () { // 请求完成 if (this.status === 200) { // 返回200 var blob = this.response; var reader = new FileReader(); reader.readAsDataURL(blob); // 转换为base64,可以直接放入a表情href reader.onload = function (e) { // 转换完成,创建一个a标签用于下载 var a = document.createElement('a'); a.download = 'data.xlsx'; a.href = e.target.result; $("body").append(a); // 修复firefox中无法触发click a.click(); $(a).remove(); } } };