你的管理台有一个功能是点击[查看文件],下载文件到本地的功能。你可能自然的向后台接口(可能是 Nodejs 的一个 Restful Api)请求下载。但是你发现你后台的 Nodejs 虽然设置了正确的响应头(Content-position, Content-type)却还是没有弹出保存文件的框。
原因是未经过处理的 ajax(如jquery ajax请求) 请求不能处理正确的二进制(流)类型的文件。
下面我总结了几种方式可以解决此问题-> 📚🌲
利用iframe
Nodejs 端正常的设置相应头,Content-disposition: attachment, filename=
。然后读到服务器上对应的文件赋值给 ctx.body
即可。下面是一种参考的代码:
1 | const filePath = path.join(path.resolve(__dirname, '../uploads'), ${fileStamp}) |
前端利用 iframe 的 src 属性,进行重新赋值。注意 iframe 设为 display: none
属性。
1 | <iframe ref="downloadIframe" src="" frameborder="0" style="display: none;"></iframe> |
利用URL.createObjectURL
URL.createObjectURL() 静态方法会创建一个 DOMString,其中包含一个表示参数中给出的对象的URL。这个 URL 的生命周期和创建它的窗口中的 document 绑定。这个新的URL 对象表示指定的 File 对象或 Blob 对象。
一个 Blob对象表示一个不可变的, 原始数据的类似文件对象。Blob表示的数据不一定是一个JavaScript原生格式。 File 接口基于Blob,继承 blob功能并将其扩展为支持用户系统上的文件。(HTML5新增特性)
这种方法我已经在上篇文章刚好有用到,可以利用浏览器原生 fetch 方法,然后解析为 blob 类型。再利用a标签的 download 属性即可。参考代码如下:
1 | function fetchApi (url, data) { |
当然你可以不用 fetch 的这个方法,直接在 xhr 里进行封装。我看到 stackoverflow 上有个很好的文章,地址戳这里,我觉的最高回答者已经解释的很好了,下面引用如下:
1 | var xhr = new XMLHttpRequest(); |
大概的思路是利用 xhr
原生对象的 onload
后,进行new blob()
对象。
再执行URL.createObjectURL(blob)
的操作。
总结
其实还有别的方法,如 POST
一个请求,但是这个会刷新当前的 Url
。上面两种情况其实是两种思路。
POST
请求跟 Iframe
类似,同样还可以 window.open
或者 window.location
来做这件事情。