思路
返回的结果处理:
1.成功:返回arraybuffer文件流,前端获取文件流转码下载
2.失败:返回json,前端获取jsob转中文提示框失败原因
判断条件
后端返回的请求头header,根据content-type判断是成功还是失败,成功返回application/octet-stream;失败返回application/jso
代码实现
需要注意axios请求,一般公共封装好的请求,都会在请求拦截那里将请求头拦截,我直接用的axios请求
/* 导出表格 post方式 */
onExport() {
let params = {
body: { ...this.QueryData },
page: this.pagination.current,
pageSize: 10,
sortName: "sid",
sortOrder: "desc"
}
axios({
url: url,
method: 'POST',
data: params,
headers: 'application/json',
responseType: 'arraybuffer'
}).then( res => {
if( res.headers['content-type'].includes('application/octet-stream') ) {
/* 截取头部获取文件名 utf8转中文 */
let str = res.headers['content-disposition']
let fileName = decodeURI(str.split('=')[1].split('.xls')[0])
/* 下载文件 */
this.downloadFile(res, fileName)
} else if(res.headers['content-type'].includes('application/json')) {
let enc = new TextDecoder('utf-8')
this.$message.error(enc.decode(new Uint8Array(res.data)))
}
}).catch( err => {
this.$message.error('系统异常')
})
}
文件流的处理方式1:a标签模拟点击事件下载
/* 导出文件 bold文件流方式导出 */
downloadFile(res, fileName) {
var blob = new Blob([res.data])
const reader = new FileReader()
reader.readAsDataURL(blob)
reader.onload = (e) => {
const a = document.createElement('a')
a.download = `${fileName}.xls`
a.href = e.target.result
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
this.$message.success('导出成功')
}
},
文件流的处理方式2:使用插件下载 file-saver [npm i 就能用]
import { saveAs } from 'file-saver'
/* 导出文件 bold文件流方式导出 */
downloadFile(res, fileName) {
fileName = `${fileName}.xls`
var blob = new Blob([res.data])
saveAs(blob, fileName)
},
注意:文件命这里是后端放在请求头的content-disposition,为避免乱码,后端进行了转码,前端需要截取filename=后边的编码进行转码,再拼接。
代码如下
/* 截取头部获取文件名 utf8转中文 */
let str = res.headers['content-disposition']
let fileName = decodeURI(str.split('=')[1].split('.xls')[0])
导出失败的情况,需要将接口返回的提示转码为中文
/* 文件导出失败 utf8转中文 */
let enc = new TextDecoder('utf-8')
this.$message.error(enc.decode(new Uint8Array(res.data)))