我们都知道在前端使用vue开发管理平台的时候难免会遇到需要导出数据的情况,前端该如何导出数据呢?下面我们直奔主题。
- 首先在请求后端接口的时候需要下载excel文件,我们把excel文件下载的方法简单的封装一下,如下所示:
//utils.js
export function downloadTemplate (data, fileName = '导出文件.xlsx') {
const blob = new Blob([data])
if (window.navigator.msSaveOrOpenBlob) {
navigator.msSaveBlob(blob, fileName)
} else {
const link = document.createElement('a')
const evt = document.createEvent('HTMLEvents')
evt.initEvent('click', false, false)
link.href = URL.createObjectURL(blob)
link.download = fileName
link.style.display = 'none'
document.body.appendChild(link)
link.click()
window.URL.revokeObjectURL(link.href)
}
}
- 上面封装了导出方法,下面我们来具体操作一下如何导出:
//test.vue
import { downloadTemplate } from '@/utils'
//省略......
exportExcel () {
const qString = {
// params...
}
const loading = this.$loading({
lock: true,
text: 'Loading',
spinner: 'el-icon-loading',
customClass: 'batch_export_loading',
background: 'rgba(0, 0, 0, 0.4)'
})
apiExportList(qString).then(res => {
if (res.data) {
downloadTemplate(res.data, '我的客户.xlsx')
}
}).finally(() => {
loading.close()
})
},
- 在上面已经演示了请求成功的情况,那么请求失败的话该怎么处理呢?首先为什么要单独讲请求失败的情况呢?因为在上述请求中我们设置了请求头响应数据类型
{ responseType: 'blob'}
,在请求成功的情况下是直接返回excel的文件流再下载没有毛病。比如说我们先筛选一个条件,查出来的数据为空,然后在导出,那么问题就来了,后端会返回res.data.data.success
这个字段false
,前面成功返回文件流,后面失败返回一个json
格式数据,这要怎么搞?首先我们可以这样搞,如下:
exportExcel () {
//省略......
ExportList(qString).then(res => {
const reader = new FileReader()
reader.readAsText(new Blob([res.data], ['utf-8']))
reader.addEventListener('loadend', () => {
const result = JSON.parse(reader.result)
if (result.success) {
downloadTemplate(res.data, '我的客户.xlsx')
} else {
this.$message.error(result.message)
}
})
})
},
如此操作一番,貌似没有问题。但是仔细想一下,在成功的时候是没有json
返回的,返回的是一个excel文件流,在这个地方result.success
这儿的时候就抛错了。
- 最后,是让后端返回请求响应码为
400
,错误的时候统一在请求拦截器中处理,如下:
//request.js
import axios from 'axios'
import { Message } from 'element-ui'
const service = axios.create({
baseURL: process.env.BASE_API
timeout: 10000,
retry: 0, // 请求失败重新请求的次数
retryDelay: 1000 // 重新请求的间隔时间
})
service.interceptors.request.use(config => {
//config.headers.Authorization = store.getters.token
//...
return config
},error => {
if (error.response.status === 400 && error.response.config.responseType === 'blob') {
// 导出blob流失败时转为文本
const reader = new FileReader()
reader.addEventListener('loadend', function () {
const result = JSON.parse(reader.result)
Message.error(result.message)
})
reader.readAsText(new Blob([error.response.data], ['utf-8']))
}
Promise.reject(error)
})
这样就可以完美解决问题了,其实也可以在res.data.data
中返回excel文件流,多包一层数据结构,前端在拿到请求的响应做相应的操作,大家也可以尝试下。