今天下午,突然发现项目群中小伙伴在讨论文件下载的接口出问题了,摸鱼的我只好跳出来问了问(此时的我正在云顶之奕ing
),得知是浏览器的响应已经接收到了文件流,但是浏览器却没有下载该文件,只好暂停了我的摸鱼大业,开始上班。
undefined
欸,问题出现了,没有找到文件流,当然下载不了
这个项目的axios请求是之前封装好了的,所以我直接去响应拦截器中,打印了一下response,这里能看到文件流的。
这不就找到问题了,是响应拦截器将文件流拦下来不让他过,需要想办法给它一个通行证。
我是不会承认之前封装的时候忘了考虑文件情况了的,绝对!不会!!!
首先去到我们统一的api管理的文件处,给axios请求加一个responseType
字段,告诉它返回的是blob
responseType:blob
接着利用这个字段,在我们的拦截器中去判断,返回的东西到底是不是文件流
service.interceptors.response.use((res) => {
const { config, headers } = res
// 判断是否是文件流
if(config.responseType == 'blob'){}
}
接下来,在大括号里面,直接return res.data
就可以了。
但是我已经出手了,能这样就收手么?不能!咱要做到完美~
这是后端传来用来放文件名的头,我要将文件名和后缀从中取出,为了后面下载的时候使用。
正好前几天学了切割url参数,这个地方刚好用到
const file = headers['content-disposition'].split(';')[1].split('=')[1]
const fileGroup = file.split('.')
const fileName = fileGroup[0]
const fileEnd = fileGroup[1]
return {blob:res.data, fileName, fileEnd}
切下来之后,直接return回页面里,在页面中使用就好。
看一下切割好的样子吧:
有了文件流,文件名字,后缀,只需要一个下载函数,我们就可以任意的下载后端传过来的文件了,这里我的想法是a
标签。
readBlobDown(result, filename){
let blob = result
let reader = new FileReader()
reader.readAsDataURL(blob)
reader.onload = function(e) {
// 转换完成,创建一个a标签用于下载
let a = document.createElement('a')
a.download = filename // 设置下载的文件名称
a.href = e.target.result
// 触发click 达成下载事件触发
a.click()
}
}
去项目的utils下创建这么一个工具函数,传入参数是文件流和文件名字,这样传进来什么,都可以直接下载,简直完美!
模板字符串当然要用起来~
使用方法:
readBlobDown(blob,`${fileName}.${fileEnd}`)
好了好了,搞定了,我要继续我的摸鱼大业了~
我是Ned
,一个前端学习者,希望可以同大家一起学习进步,一起加油~
你可以在掘金找到我:Ned
也可以前往我的个人博客:blog.wangez.site
可以来交换友链哟~