在一个地方连续踩了2次坑,对于我这种记性不好的来说,只能博客赶紧记录一下了,文件流下载的适用场景是: 前端页面点击导出按钮后调取后端接口,接口返回数据,然后通过下载函数处理,下载保存到本地,下面分享下都遇到哪些坑:
一. 接口需配置 responseType
坑一: responseType配置项必须传,一般只在前端配置,后端不做处理,此处的type就是调用该接口时传进来的文件转换类型,意思是前端接收到流后以什么类型转换,然后可供下载
-
// xx 导出
-
export
function
handleExport(
params, type) {
-
return
request({
-
url:
`xxxxx/export`,
-
method:
'post',
-
data: params,
-
responseType: type,
-
})
-
}
二. 调用接口并传参
下图中,params是自己接口的正常传参,‘blob’就是上面接口传的type类型,因为我们项目都是xls表格类型结尾的,所以我设置的blob,为什么可以自行百度,downloadFile即下载函数,下面会介绍
-
/**
-
* 导出
-
*/
-
handleExport(
) {
-
this.$confirm(
'确定要导出所有线下订单吗?',
'导出提示', {
-
confirmButtonText:
'确定',
-
cancelButtonText:
'取消',
-
}).
then(
async () => {
-
this.
exportLoading =
true
-
const exportRes =
await
handleExport(parmas,
'blob').
catch(
(err) => {
-
this.
exportLoading =
false
-
})
-
this.
exportLoading =
false
-
downloadFile(exportRes,
'线下订单明细')
-
})
-
},
坑二: 这里需要注意的是,因为现在前端大部分项目都使用axios拦截器,而文件流接口回来的数据可能与其他接口不统一,导致被拦截器拦截,那拿到的数据肯定不对,怎么转换都是错的啦,我就在此处绊住半天,下面是我自己项目中的处理方式,你们可以根据自己项目的数据处理
-
/**
-
* @description axios响应拦截器
-
*/
-
instance.
interceptors.
response.
use(
-
(response) => {
-
console.
log(response)
// 此处可以打印先看下返回的数据格式,方便下面处理
-
const { config, data, status } = response
-
const exportUrlList = [
`${shopUrl}/orderItem/export`]
-
if (exportUrlList.
includes(config.
url)) {
-
// 导出接口,返回数据格式与其他不统一,需特殊处理
-
if (status ===
200) {
-
return data
-
}
else {
-
Vue.
prototype.$baseNotify(
'导出失败!',
'提示',
'error')
-
return
Promise.
reject({
-
noShow:
true,
-
message:
'导出失败!',
-
})
-
}
-
}
else {
-
return
handleData(response)
// 这是其他的统一处理的函数
-
}
-
},
-
(error) => {
-
const { response } = error
-
if (response ===
undefined) {
-
Vue.
prototype.$baseMessage(
'未可知错误,大部分是由于后端不支持跨域CORS或无效配置引起',
'error')
-
return {}
-
}
else
return
handleData(response)
-
}
-
)
三. 下载,保存到本地
成功拿到返回数据后,就是进行下载 ,下图就是下载的处理过程,可以拿去用,new Blob 还可以传入其他参数,此处我没有传,如果特殊处理可以自己传,自行了解new Blob的用法,此处用的moment可以npm下载,当然前端项目基本都会用到
-
/**
-
* @description 下载文件流
-
* @param response 文件流
-
* @param fileName 文件名称
-
*/
-
export
function
downloadFile(
response, fileName) {
-
const blob =
new
Blob([response])
-
const a =
document.
createElement(
'a')
-
const
URL =
window.
URL ||
window.
webkitURL
// 兼容webkix浏览器,处理webkit浏览器中href自动添加blob前缀,默认在浏览器打开而不是下载
-
a.
href =
URL.
createObjectURL(blob)
// 根据解析后的blob对象创建URL 对象
-
a.
download =
`${fileName}-` +
moment().
format(
'YYYYMMDDHHmmss') +
'.xls'
-
//此写法兼容可火狐浏览器
-
document.
body.
appendChild(a)
-
let evt =
document.
createEvent(
'MouseEvents')
-
evt.
initEvent(
'click',
false,
false)
-
a.
dispatchEvent(evt)
-
document.
body.
removeChild(a)
-
}
四. 文件保存后,验证是否可以正常打开
坑三:保存后,如果能正常打开且显示数据正常,请忽略下面的问题。如果打开发现还是会提示文件格式不正确,什么鬼?各种查阅后,发现是mock请求导致的,mock请求将request改为了MockXMLHttpRequest(如下图所示),data也是乱码
解决方法: 屏蔽掉mock引入,再调接口,返回数据如下图所示,data返回时Blob格式,就ok了 ,此时下载保存到桌面就没问题啦!
当然以上只是我遇到的问题,如果情况不符合你的预期,那你再去查查别的相关资料,希望能帮到你
转载:https://blog.csdn.net/weixin_41326021/article/details/125527072