前段时间工作中碰到了后端接口返回文件流,前端进行下载的需求
- 首先是axios配置,
import axios from 'axios'
/*
对于某些成熟项目,在已经封装好的组件里面另外增加逻辑可能会对原有代码产生影响
可以单独新建一个axios实例。
这个axios 实例不受已经写好的axios配置的影响
例如:拦截器、错误处理、响应结构、等等
*/
const instance = axios.create()
/*
如果你不想新建一个axios实例去做这件事,而是想在原有的返回判断中去增加逻辑
你可以通过这个方法去判断返回结果是不是blob类型
*/
const isBlob = respone.data instanceof Blob // isBlob 为 true 代表返回的是文件流
/*
封装axios
path:请求url
base:接口地址
params:参数
config:配置
*/
const blobFetch = (path, base) => (params, config = {}) => new Promise((resolve, reject) => {
const req_data = getFormData(params)
instance.post(base + path, req_data, config).then(res => {
res ? resolve(res.data) : null
}).catch(err => {
reject(err)
})
})
const export = blobFetch(接口地址)
// 使用 重点config 配置 responseType: 'blob'
export(参数,{responseType: 'blob'})
/*
axios 文档
`responseType` 表示浏览器将要响应的数据类型
选项包括: 'arraybuffer', 'document', 'json', 'text', 'stream'
浏览器专属:'blob'
responseType: 'json', // 默认值
`responseEncoding` 表示用于解码响应的编码 (Node.js 专属)
注意:忽略 `responseType` 的值为 'stream',或者是客户端请求
*/
- 拿到文件流进行下载
function exportBlob() {
const params = {
...P,
}
export(params,{responseType: 'blob'}).then(res => {
// type 代表了下载的blob 的媒体类型
// 目前我只做过两个类型,我这里下载的是xlsx
// pdf 类型 为 type: 'application/pdf;charset=UTF-8'
const blob = new Blob([ele], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8'})
const a = document.createElement("a")
const URL = window.URL || window.webkitURL
// URL.createObjectURL()方法会根据传入的参数创建一个指向该参数对象的URL. 这个URL的生命仅存在于它被创建的这个文档里. 新的对象URL指向执行的File对象或者是Blob对象.
const href = URL.createObjectURL(blob)
a.href = href
// 比较烦的一点是命名得由前端命名,当然没有命名需求的话也可以不写
a.setAttribute('download', 'filename.xlsx')
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
/*
URL.revokeObjectURL()方法会释放一个通过URL.createObjectURL()创建的对象URL. 当你要已经用过了这个对象URL,然后要让浏览器知道这个URL已经不再需要指向对应的文件的时候,就需要调用这个方法.
具体的意思就是说,一个对象URL,使用这个url是可以访问到指定的文件的,但是我可能只需要访问一次,一旦已经访问到了,这个对象URL就不再需要了,就被释放掉,被释放掉以后,这个对象URL就不再指向指定的文件了.
比如一张图片,我创建了一个对象URL,然后通过这个对象URL,我页面里加载了这张图.既然已经被加载,并且不需要再次加载这张图,那我就把这个对象URL释放,然后这个URL就不再指向这张图了.
*/
URL.revokeObjectURL(href)
})
}
如果你有别的文件类型需求可以看这个 Media Types