没想到,axios下载文件竟然比fetch好用
前言
还是和上篇一样,是关于导出excel的问题。好像是生产上导出的excel有问题,具体是啥没和我说,当然和我上篇写的没有什么关系,这是另一个模块历史遗留的问题。反正到我手里的任务就是更改导出的接口让后端去做表格。
原来的写法
原来的写法很粗暴,直接用window.location
去跳转下载链接就把excel下载了,后端具体怎么做我的不清楚,前端的逻辑就是有一个固定的地址,然后通过query去传参让后端知道该导出什么样的excel表格。
function exportExcel(params){
const url = 'xxxxx/exportExcel?id=params.id&type=params.type'
window.location = url
}
content-disposition
基础没学好应该也是会这样的一个疑问,为什么我在浏览器中输入一个地址就会下载文件
,是的我也是,所以我去查了一下,主要是由于Content-Disposition
这个响应头字段。它告诉浏览器该文件是作为附件下载,还是在浏览器中直接打开。如果该字段的值为 attachment
,则浏览器会将文件下载到本地;如果该字段的值为inline
,则浏览器会尝试在浏览器中直接打开文件。
语法格式
- 其基本语法格式为:
Content-Disposition: attachment; filename="filename.ext"
或Content-Disposition: inline; filename="filename.ext"
。- 其中,
attachment
表示将内容作为附件下载,这是最常见的用于文件下载的设置;而inline
则表示在浏览器中内联显示内容,即直接在浏览器窗口中展示,而不是下载。filename
参数用于指定下载文件的名称,若不指定,浏览器可能会根据服务器返回的其他信息或自身的默认规则来确定文件名。
标题党?
才不是啊,因为我要对接的接口变成post请求,用原来这种方式肯定是不行的,这个时候我就想到了我之前写过的类似需求,就是用fetch。但是一直请求不成功,后端一直报请求参数异常。
fetch
function exportExcel(data){
fetch(`xxxxxxx/ExportExcel`, {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Authorization': 'xxxxxxxxxxxxxxxxxxxxxxxxxx'
}
}).then(res => {
const readableStream = res.body
if (readableStream) {
return new Response(readableStream).blob()
} else {
console.error('No readable stream available.')
}
}).then(blob => {
// 创建一个下载链接
const downloadLink = document.createElement('a')
downloadLink.href = URL.createObjectURL(blob)
// 设置下载属性,指定文件名
downloadLink.download = '测试.xlsx'
// 模拟点击下载链接
downloadLink.click()
// 释放 URL 对象
URL.revokeObjectURL(downloadLink.href)
})
}
我感觉我写的没有什么毛病啊,fetch第一个then回调转成blob数据类型,第二个then模拟a标签点击下载。但是后端老给报参数类型异常。
我本来想让后端给我看看什么原因的,是什么参数没传对,还是什么请求头不对,但是他就老给甩一张swagger的请求成功的截图,根本不会帮你去看日志是因为什么原因。当然,swagger能调成功,说明接口肯定是没问题的,肯定是我没有传对东西,但是就挺烦的,都没有沟通欲望了,想着自己去换种方式去解决,然后我就想着用axios去试一下,没想到成功了
axios
function exportExcel(data) {
axios({
method: 'post',
url: `xxxxx/ExportExcel`,
data,
responseType: 'blob'// 这里就是转化为blob文件流
}).then(res => {
console.log(res, 'res')
// 创建一个下载链接
const downloadLink = document.createElement('a')
downloadLink.href = URL.createObjectURL(res.data)
// 设置下载属性,指定文件名
downloadLink.download = '测试.xlsx'
// 模拟点击下载链接
downloadLink.click()
// 释放 URL 对象
URL.revokeObjectURL(downloadLink.href)
})
}
这里通过responseType
设置blob
值,就会自动将响应的东西转成blob二进制的格式内容,然后还是通过模拟a标签下载。相比于fetch,我们要在第二个then中对数据进行转换,而axios配置一个参数就行了。
总结
现在大部分的项目中,基本都是使用axios封装的交互方法,所以我们其实用axios是最好的,只需要配置一个参数就可以下载excel,相较于fetch来说,代码是比较简洁一点。虽然我这里fetch是没有成功的,但是放心,肯定是没有问题,是可以这样下载excel的,我估摸着应该是请求头的原因吧,可能是后端做了什么对请求头的处理,我也不知道,但是我之前做这个需求都是用fetch肯定没问题。
来源:juejin.cn/post/7450310230536208418