a标签下载
这种方式下载比较简单,直接下载二进制数据流的文件 这种写法需要设置代理服务 downloadModel() 即后端同事给的路径比如: /api/downModel?id=${id} 不过前面需要补充完整 xx.xx.xx.xx:8080
const a = document.createElement('a')
a.href = downloadModel()
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
优点:简单,快速,文件名和格式均由后端提供
缺点:只能get方式,不可以传递data和自定义header(token等验证)
axios方式下载
axios方式由于后端返回的是数据流(如下图),需要转换成前端的blob对象
export function downloadByData(data: BlobPart, filename: string, mime?: string, bom?: BlobPart) {
const blobData = typeof bom !== 'undefined' ? [bom, data] : [data]
const blob = new Blob(blobData, { type: mime || 'application/octet-stream' })
const blobURL = window.URL.createObjectURL(blob)
const tempLink = document.createElement('a')
tempLink.style.display = 'none'
tempLink.href = blobURL
tempLink.setAttribute('download', filename)
if (typeof tempLink.download === 'undefined') {
tempLink.setAttribute('target', '_blank')
}
document.body.appendChild(tempLink)
tempLink.click()
document.body.removeChild(tempLink)
window.URL.revokeObjectURL(blobURL)
}
request.ts
export const exportData = data =>
request({
url: 'api/export',
method: 'POST',
data,
responseType: 'blob',
})
调用
exportData().then(res => {
downloadByData(res,'测试文件,'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
})
优点:可以使用post/get方式,可以携带请求头header
缺点:相对于a标签方式代码多一些,需要做blob转换,需要自定义文件名,以及文件类型要与后端保持一致,否则会导致下载下来无法打开
遇到的坑:
- axios方式中接口请求的responseType值一定设置‘blob’,或者其他类型文件;否则出现文件损坏打不开的情况
- 后端返回的是二进制数据流,输出如下图
所以在使用downloadByData()工具类时,第一个参数不能直接放入上图文件流,这样下载下来的文件也会出现损坏打不开的情况,而是axios的interceptors.response.use(response=>{})返回的第一个参数response,不能返回response.data即上图的blob对象;
tips:封装axios的request工具函数,判断接口返回的是否json还是数据流的方式:response.data instanceof Blob