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;
}複製代碼