项目背景:vue-cli3.0项目中已经进行二次接口封装,调用导出文件流接口
方法一
运用此方法,导出文件的名称由后端统一命名,前端无法自定义导出文件名称
// 定义 downloadApi.js
import request from '../request'
import axios from 'axios'
const doExport = (url, params = {}) => {
console.log(axios.create().baseURL)
let downloadUrl = 'api' + url
var xhr = new XMLHttpRequest()
xhr.open('POST', downloadUrl, true)
xhr.setRequestHeader(
'_token', sessionStorage.getItem('token')
)
xhr.setRequestHeader(
'Content-Type', 'application/json;charset=UTF-8'
)
xhr.responseType = 'blob'
xhr.onload = function () {
if (this.status === 200) {
var blob = this.response
if (navigator.msSaveBlob == null) {
var a = document.createElement('a')
var headerName = xhr.getResponseHeader('Content-disposition')
var fileName = decodeURIComponent(headerName).substring(20)
a.download = fileName
a.href = URL.createObjectURL(blob)
document.querySelector('body').append(a) // 修复firefox中无法触发click
a.click()
URL.revokeObjectURL(a.href)
a.remove()
} else {
navigator.msSaveBlob(blob, fileName)
}
}
}
xhr.send(JSON.stringify(params))
}
export default {
doExport
}
在文件中引用
// index.vue
import downloadApi from '@/utils/downloadApi'
doExport () {
downloadApi.doExport('/yourself url', `yourself params`)
}
方法二
运用此方法,前端可以自定义导出文件名称
// 定义 downloadApi.js
import request from '../request'
import axios from 'axios'
const exportTask = (url, data, name) => request({
url,
data,
responseType: 'blob',
method: 'POST'
}).then(res => {
download({
data: res,
name
})
})
const download = options => {
console.log(options)
let blob = new Blob([options.data], { type: options.type || 'application/vnd.ms-excel' })
if ('download' in document.createElement('a')) {
let downloadElement = document.createElement('a')
let href = window.URL.createObjectURL(blob)
downloadElement.href = href
downloadElement.download = options.name
document.body.appendChild(downloadElement)
downloadElement.click()
document.body.removeChild(downloadElement)
window.URL.revokeObjectURL(href)
} else {
window.navigator.msSaveBlob(blob, options.name)
}
}
export default {
exportTask
}
在文件中引用
// index.vue
import downloadApi from '@/utils/downloadApi'
doExport () {
downloadApi.exportTask('/yourself url', `yourself params`, 'custom_export_name')
}
小结
1- 以上两种方法都是
post请求,如果接口是get请求,对应修改即可;也可以把这两种方法合并到一起并export,方便调用和查看。
2- 如果为了方便接口统一管理而不想在.vue文件中使用url,可以参考使用下面的调用方式(以方法二为例)
// 定义 /utils/downLoad.js
export const download = options => {
let blob = new Blob([options.data], { type: options.type || 'application/vnd.ms-excel' })
if ('download' in document.createElement('a')) {
let downloadElement = document.createElement('a')
let href = window.URL.createObjectURL(blob)
downloadElement.href = href
downloadElement.download = options.name
document.body.appendChild(downloadElement)
downloadElement.click()
document.body.removeChild(downloadElement)
window.URL.revokeObjectURL(href)
} else {
window.navigator.msSaveBlob(blob, options.name)
}
}
// 定义 /api/myApi
const exportTemplate = params => request({
url: 'yourself url',
params,
responseType: 'blob',
method: 'GET'
})
export default {
exportTemplate
}
// 引用
import { download } from '@/utils/downLoad'
import myApi from '@/api/myApi'
doExport (item) {
myApi.exportTemplate({ id: item.rowId }).then((res) => {
download({ data: res, name: item.templateName + '列表' })
})
}
遇到的问题及解决方案
问题一 vue element admin 后台请求Uncaught (in promise) Error: Error at webpack_exports.def 问题
一般出现这种问题的原因是在代码中写入了请求拦截,限制了响应返回值条件导致出错,检查修改即可。
问题二 通过后台返回下载文件到本地打开显示乱码
在封装的请求方法里添加
responseType: 'blob' // 或者 'arraybuffer'