开启AdminJS成长之旅!这是我参与「AdminJS日新计划 · 12 月更文挑战」的第15天,点击查看活动详情
群友又提了个问题,前端如何下载后端返回的二进制文件,比如下载一个word文件;我寻思着之前不是写过前后端分别实现下载文件的功能吗?怎么还有问题,果然,在仔细了解需求后发现前文《和后端对线 | 前端如何保存base64字符串为文件》并没有说明这种情况,今天就给大家来列举一下浏览器下载文件的各种姿势,如有遗漏欢迎评论区补充
场景
目前想到的是这3个场景
- 后端返回base64,或者其他编码格式,前端转码下载
- 后端返回二进制,前端直接下载
- 后端接口需要填写参数比如,post一些数据,才返回二进制;前端请求接口后下载二进制
1. 后端返回base64,或者其他编码格式,前端转码下载
对于这种情况,在前文中有详细说明,主要步骤如下
对base64(其他)进行解码 -> ASCII码字符串 -> uint8Array -> Blob
两行代码搞定
const data = new Uint8Array(atob(base64).split('').map((v) => v.charCodeAt()))
const blob = new Blob([data])
保存下载就很简单了,用a标签下载即可
const $a = document.createElement('a')
$a.setAttribute('download','a.gif')
$a.href = URL.createObjectURL(blob)
$a.click()
如果是其他编码格式,也是一样的步骤,最终都是转成blob格式下载
2. 后端返回二进制,前端直接下载
这个就更简单了,只要在前端用a标签设置href为下载地址即可,其他内容都由服务端控制
<a href="http://localhost:2345/download">直接下载二进制</a>
如果用js
const $a = document.createElement('a')
$a.href = "http://localhost:2345/download"
$a.click()
3. 后端接口需要填写参数比如,post一些数据,才返回二进制;前端请求接口后下载二进制
这个情况其实和第二种情况差不多,也是后端直接返回二进制文件,只不过接口需要参数校验;这也是今天要补充说明的新场景;同样很简单,结合场景1,2的方法,在请求之后获取到blob文件然后通过a标签下载就可以了
function downloadFile() {
fetch('http://localhost:2345/download').then(r => r.blob()).then((res) => {
const aLink = document.createElement('a')
aLink.setAttribute('download', 'a.gif')
aLink.href = URL.createObjectURL(res)
aLink.click()
})
}
那么后端设置的文件名要怎么获取呢?
答案就是在response header获取即可
function downloadFile() {
fetch('http://localhost:2345/download').then(async r => {
const res = await r.blob()
return {
res: res,
fileName: r.headers.get('file-name')
}
}).then(({ res, fileName }) => {
const aLink = document.createElement('a')
aLink.setAttribute('download', fileName)
aLink.href = URL.createObjectURL(res)
aLink.click()
})
}
对了,这里有个深坑,如果跨域的话,记得设置一下跨域头,这样才能前端获取到file-name这个header
response.writeHead(200, {
"Content-Disposition": "attachment; filename=a.gif",
"Content-Type": "image/gif; ",
"Access-Control-Allow-Origin": "*",
"file-name": "test.gif",
"Access-Control-Expose-Headers": "file-name",
});
源码
所有前后端源码都在这个地址github.com/lulusir/dow… 记得给个star哈
觉得本文有帮助的同学记得给个评论点赞收藏,一键三连ღ( ´・ᴗ・` )
推荐阅读
使用Typescript实现中间件模式,顺便发了个npm包
在线等,后端悄悄改了接口文档被我抓住了怎么办?
和后端对线 | 前端如何保存base64字符串为文件
释放生产力 | Yapi,swagger2,swagger3生成请求代码
什么?在React中也可以使用vue响应式状态管理
clean-js | 在hooks的时代下,使用class管理你的状态
clean-js | 手把手教你写一个羊了个羊麻将版
有没有一种可能,你从来都没有真正理解async