export const exportDataByPost = async (url, params) => {
console.log('------exportDataByPost------');
let AFFTK = localStorage.getItem('AFFTK')
const token = `Bearer ${AFFTK}`
const merchant = localStorage.getItem('MID') ? localStorage.getItem('MID').split('_')[1] : ''
try{
const response = await fetch(baseUrl + prefix + url, {
mode: 'cors',
method: 'POST',
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": token,
merchant,
},
body: JSON.stringify(params),
})
if (response.headers.get('content-type') !== 'application/json') {
response.blob().then((blob) => {
const a = window.document.createElement('a');
const downUrl = window.URL.createObjectURL(blob);// 获取 blob 本地文件链接 (blob 为纯二进制对象,不可以直接保存到磁盘上)
let filename = "download.xls";
if (response.headers.get('content-disposition') && response.headers.get('content-disposition').indexOf("filename=") !== -1) {
filename = response.headers.get('content-disposition').split('filename=')[1];
a.href = downUrl;
a.download = `${decodeURI(filename.split('"')[1])}` || "download.xls";
a.click();
window.URL.revokeObjectURL(downUrl);
}
}).catch(error =>{
message.error(error);
});
} else {
let res = await response.json();
message.error(res.msg);
}
}catch(err){
message.error('下载超时');
}
}复制代码
前端axios获取二进制流下载excel并解决没法获header问题前端
Fetch / ajax 不能获取response中的全部headers的解决方法(适用nginx)ios
/**
* 对应导出请求,返回的响应为json对象,不是文件流的状况,
* 须要从新请求一遍
* 不过不带responseType: 'blob'
* @param url 请求地址
* @param params 请求表单参数
*/
function exportDataByJson (url, params) {
axios({
url: baseUrl + url,
method: 'post',
data: params
}).then((res) => {
Message({
type: 'error',
message: res.msg
})
}).catch((err) => {
console.error(err)
})
}
/**
* 导出文件post请求
* @param url 请求地址
* @param params 请求表单参数
*/
export async function exportDataByPost (url, params) {
console.log('------exportDataByPost------')
try {
const response = await axios({
url: baseUrl + url,
method: 'post',
responseType: 'blob', // 这句话很重要
data: params
})
// 当导出请求,返回的响应为json对象时,
// 根本就不会走到这里,直接走到后面catch里面了
// 因此下面console.log(response)根本不会打印出来
console.log(response)
if (response.status !== 200) {
console.log('网络或服务器异常!')
return
}
let blob = new Blob([response.data], { type: response.headers['content-type'] })
const a = window.document.createElement('a')
const downUrl = window.URL.createObjectURL(blob)// 获取 blob 本地文件链接 (blob 为纯二进制对象,不可以直接保存到磁盘上)
let filename = 'download.xls'
if (response.headers['content-disposition'] && response.headers['content-disposition'].indexOf('filename=') !== -1) {
filename = response.headers['content-disposition'].split('filename=')[1]
a.href = downUrl
a.download = `${decodeURI(filename.split('"')[1])}` || 'download.xls'
a.click()
window.URL.revokeObjectURL(downUrl)
}
} catch (err) {
console.error(err.type)
if (err.type === 'application/json') {
console.log('导出请求返回的是json数据啊啊啊啊啊')
// 再次请求接口,获取错误提示信息,不过要去掉responseType: 'blob',
exportDataByJson(url, params)
}
}
}复制代码
responseType: 'blob'
responseType: 'blob'
,这句代码很重要。
postExportFile (params, url) {
// params是post请求须要的参数,url是请求url地址
let form = document.createElement('form')
form.style.display = 'none'
form.action = url
form.method = 'post'
document.body.appendChild(form)
for (let key in params) {
let input = document.createElement('input')
input.type = 'hidden'
input.name = key
input.value = params[key]
form.appendChild(input)
}
let inputToken = document.createElement('input')
inputToken.type = 'hidden'
inputToken.name = 'token'
inputToken.value = localStorage.getItem('token')
form.appendChild(inputToken)
form.submit()
form.remove()
},
exportData () {
let startDate = ''
let endDate = ''
if (this.queryValues.date) {
let [sDate, eDate] = this.queryValues.date
startDate = moment(sDate).format('YYYY-MM-DD')
endDate = moment(eDate).format('YYYY-MM-DD')
}
let qDate = deepCopy(this.queryValues)
delete qDate.date
let params = Object.assign(
{},
{
start_date: startDate,
end_date: endDate,
page: this.currentPageNo,
page_size: this.pageSize
},
qDate
)
exportDataByPost('/report/order/export', params)
/* this.$store.dispatch('reportOrderExport', params).then(res => {
if (res.data) {
this.postExportFile(params, baseUrl + '/report/order/export')
}
}) */
}复制代码
因为fetch没法像axios同样经过timeout配置项实现前端请求超时控制,须要本身封装,如下为本身封装的带超时控制的导出功能。web
ES6 fetch(input, init) 设置超时(timeout)
ajax
让fetch也能够timeout
json
/**
* 导出文件公共函数
* 因为fecth请求,没有超时timeout配置项,
* 须要封装实现相似于axios timeout的功能
* 在此背景下,特封装了一个带前端请求超时控制的fecth导出文件公共函数
*/
import fetch from 'dva/fetch'
import { message } from 'antd'
import { baseUrl } from './config'
const prefix = '/api'
const _fetch = (fetchRequest, timeout) => {
timeout = timeout > 0 ? timeout : 0;
let breaker = new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('请求超时'))
}, timeout);
});
/*
* Promise.race(iterable)方法返回一个promise,
* 这个promise在iterable中的任意一个promise被解决或拒绝后,
* 马上以相同的解决值被解决或以相同的拒绝缘由被拒绝。
*/
return timeout === 0 ? fetchRequest : Promise.race([fetchRequest, breaker]);
};
const exportDataByPostFn = async (url, params) => {
let AFFTK = localStorage.getItem('AFFTK')
const token = `Bearer ${AFFTK}`
const merchant = localStorage.getItem('MID') ? localStorage.getItem('MID').split('_')[1] : ''
/* 'http://localhost:8081/user/login' */
const response = await fetch(baseUrl + prefix + url, {
mode: 'cors',
method: 'POST',
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": token,
merchant,
},
body: JSON.stringify(params),
})
// response.headers.get('content-type') 多是 application/json
// 也多是 application/json; charset=utf-8
if (!response.headers.get('content-type').includes('application/json')) {
response.blob().then((blob) => {
const a = window.document.createElement('a');
const downUrl = window.URL.createObjectURL(blob);// 获取 blob 本地文件链接 (blob 为纯二进制对象,不可以直接保存到磁盘上)
let filename = "download.xls";
if (response.headers.get('content-disposition') && response.headers.get('content-disposition').indexOf("filename=") !== -1) {
filename = response.headers.get('content-disposition').split('filename=')[1];
a.href = downUrl;
a.download = `${decodeURI(filename.split('"')[1])}` || "download.xls";
a.click();
window.URL.revokeObjectURL(downUrl);
}
}).catch(error =>{
message.error(error);
});
} else {
let res = await response.json();
message.error(res.msg);
}
}
/**
* 导出excel文件post请求
* @param url 请求地址
* @param url 请求地址样例:'/commission/extra-model/export'
* @param params 请求表单参数
* @param params 格式
* {
* a: 1,
* b: 2
* }
*/
export const exportDataByPost = async (url, params) => {
console.log('------exportDataByPost------');
let fetchRequest = exportDataByPostFn(url, params)
let res = await _fetch(fetchRequest, 10 * 1000)
return res;
}复制代码