記資料匯出&&bold物件轉json&&下載判斷資料狀態碼
阿新 • • 發佈:2020-08-12
起因就是要做一個數據匯出的功能,今天提了個bug就是沒有資料的時候後端資料code碼返回的4001,前端沒有判斷直接做了下載處理,結果直接把錯誤資訊下載了下來。
描述:當下載檔案時,axios配置responseType: ‘blob’,此時後臺返回的資料會被強制轉為blob型別;如果後臺返回代表失敗的data,前端也無法得知,依然會下載得到名為undefined的檔案。
解決:將blob轉回json格式,通過code判斷是否下載成功
主要技術點:FileReader
先上最後實現的完整程式碼:
axios({
baseURL: './',
url: `${ this.uuurl}/system/export/index`,
method: 'get',
responseType: 'blob',
params: params,
data: {}
})
.then((res) => {
let _that = this;
const data = res.data;
// 有可能下載失敗,返回{code: '500'},但responseType: 'blob'會把data強制轉為blob,導致下載
// 解決:將已轉為blob型別的data轉回json格式,判斷是否下載成功
let reader = new FileReader();
reader.readAsText(data, 'utf-8');
reader.onload = function () {
//本來是沒有做這個try catch,但是其實不報錯的時候下載的話是text/html,出錯的話是application/json格式
try {
let jsondata = JSON.parse(reader.result)
if (jsondata && jsondata['code'] && jsondata['code'] != 200) {
// console.log('下載失敗')
_that.$message.error(jsondata.err_msg);
// _that.dialogVisible = false;
}
}catch(err){
// console.log("可以去下載")
const content = res.data;
const blob = new Blob([content]);
const fileName = `使用者資料_${new Date().toLocaleString()}` + '.xls';
if ('download' in document.createElement('a')) {
const link = document.createElement('a');
link.download = fileName;
link.style.display = 'none';
link.href = URL.createObjectURL(blob);
document.body.appendChild(link);
link.click();
URL.revokeObjectURL(link.href);
document.body.removeChild(link);
_that.$message.success('匯出資料成功');
_that.dialogVisible = false;
} else {
_that.$message.error('匯出資料失敗');
}
}
};
})
.catch((error) => {
console.log(error);
});
以下是參考文章:
一、將blob返回值轉為json資料
原文連結:https://blog.csdn.net/qq_41078029/article/details/98616815
let data = error.response.data;
if (error.request.responseType === 'blob') {
var reader = new FileReader();
reader.readAsText(data, 'utf-8');
reader.onload = function () {
data = JSON.parse(reader.result);
}
} else {
}
二、axios 的responseType 型別動態設定
原文連結:https://segmentfault.com/q/1010000014569305
我們不需要根據伺服器返回的情況去隨機設定responseType
1、我們要明白,我們在請求下載檔案的api時候,可能給我們的返回值有兩種情況:
- 直接給我們了我們想要的檔案流
- 還有可能得到了JSON返回資料,讓我們展現提示出資訊或者被叫為錯誤資訊
2、理解responseType
axios中這樣描述的:responseType`表示伺服器響應的資料型別,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
不過我經常用blob,其實用什麼都無所謂,主要看在拿到返回值的時候如何處理。
3、處理返回值的不同情況
根據response.type返回內容的MIME TYPE 來判斷是要下載檔案,還是要去做一些JSON資料提示什麼的操作。如果是JSON型別那就把Blob通過readAsText轉為JSON格式。
這種方式通過測試IE10和IE10以上版本。
const API = axios.create({ baseURL: API_HOST }) API({ method: 'get', url: file.url, responseType: 'blob' }).then(response => { const type = response.type || null //relType你所下載的檔案型別,這裡是xlsx const relType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' if (type.includes(relType)) { /**做檔案下載 */ return } if (type.includes('application/json')) { let reader = new FileReader() reader.onload = e => { if (e.target.readyState === 2) { let res = {} res = JSON.parse(e.target.result) console.info('back:: ', res) } } reader.readAsText(response) } })
三、下載檔案時axios配置responseType: 'blob'判斷下載是否成功(避免後臺返回失敗標識時依然下載undefined檔案)
原文連結:https://blog.csdn.net/qq_37246828/article/details/90080614
axios({ method: ‘post’, baseURL: ‘’, url: ‘’l, timeout: 3000, headers: {}, data: options.method.toLowerCase() !== 'get' ? options.data : undefined, responseType: 'blob' }).then( res => { const data = res.data // 有可能下載失敗,返回{code: '500'},但responseType: 'blob'會把data強制轉為blob,導致下載undefined.excel // 解決:將已轉為blob型別的data轉回json格式,判斷是否下載成功 let r = new FileReader() r.onload = function () { // 如果JSON.parse(this.result)不報錯,說明this.result是json字串,是下載報錯情況的返回值,彈框提示 // 如果JSON.parse(this.result)報錯,說明下載成功,進入catch try { let resData = JSON.parse(this.result) // this.result為FileReader獲取blob資料轉換為json後的資料,即後臺返回的原始資料 if (resData && resData['code'] && resData['code'] === '500') { alert(‘下載失敗’) } } catch (err) { let fileName = res.headers['content-disposition'] // 獲取檔名 if (fileName && fileName.length >= 2) { fileName = fileName.split('=')[1] } fileName = decodeURIComponent(fileName) // 相容ie11 if (window.navigator.msSaveOrOpenBlob) { try { const blobObject = new Blob([data]) window.navigator.msSaveOrOpenBlob(blobObject, fileName) } catch (e) { console.log(e) } return } let url = window.URL.createObjectURL(new Blob([data])) let link = document.createElement('a') link.style.display = 'none' link.href = url link.setAttribute('download', fileName) document.body.appendChild(link) link.click() resolve(fileName) } } r.readAsText(data) // FileReader的API }).catch(res => { console.log(res) })