java后端通过HttpServletResponse 返回文件流
在Content-Disposition中插入文件名
一定要设置Access-Control-Expose-Headers,代表跨域该Content-Disposition返回Header可读,如果没有,前端是取不到Content-Disposition的,可以在统一的配置里添加
response.setContentType("application/vnd.ms-excel;charset=utf-8");
response.setCharacterEncoding("UTF-8");
// 跨域暴露Header属性Content-Disposition
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
//test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(byType.getName() , StandardCharsets.UTF_8) + ".xls");
vue前端通过 axios接收文件
老生常谈的 blob或者arraybuffer
这里以arraybuffer举例
export const exportExcel=(data: Object)=>{
return request.get( option: {
url:'/scrm/customer/exportExcel'
data,
responseType:'arraybuffer'
})
})
找你的axios封装
vue2找 request.js
vue3找service.ts
或者你们自己封装的文件
找到里边的响应拦截器
request.interceptors.response.use
service.interceptors.response.use
在返回成功的前提下单独处理
直接返回response
如果你们封装的axios跟没封装一样可以忽略
if (response.request.responseType === 'blob'
|| response.request.responseType === 'arraybuffer') {
return response
}
封装个统一的方法
TS
const download = {
object: ({data, headers}, fileName :string, contentType: string) => {
try {
const uri =headers["content-disposition"].split(";")[1].split("filename=")[1];
fileName = decodeURIComponent(uri)
contentType = headers["content-type"]
} catch (e) {
console.error(e)
}
// 老一套blob
const blob = new Blob([data],{ type: contentType})
const link = document.createElement('a')
const href = window.URL.createObjectURL(blob) // 创建下载的链接
link.href = href
link.download = fileName
link.click()
document.body.removeChild(link)
window.URL.revokeObjectURL(href)
}
}
JS
downloadObject(res, fileName, contentType) {
let data = res.data
let headers = res.headers
try {
const uri =headers["content-disposition"].split(";")[1].split("filename=")[1];
fileName = decodeURIComponent(uri)
contentType = headers["content-type"]
} catch (e) {
console.error(e)
}
// 老一套blob
const blob = new Blob([data],{ type: contentType})
const link = document.createElement('a')
const href = window.URL.createObjectURL(blob) // 创建下载的链接
link.href = href
link.download = fileName
link.click()
document.body.removeChild(link)
window.URL.revokeObjectURL(href)
}
调用
exportExcel({//请求参数}).then(res => {
// vue3
download.object(res,'','')
// vue2
this.downloadObject(res)
})
最后
需要注意的一共有两个点
第一 后端必须配置
response.setHeader(“Access-Control-Expose-Headers”, “Content-Disposition”);
第二 axios返回拦截器一定要返回完整的response,不能返回经过加工的response.data