前言:基于vue2+element-ui的一個(gè)后臺(tái)管理系統(tǒng),需求評(píng)審要加一個(gè)導(dǎo)入導(dǎo)出文件的功能,由于可能導(dǎo)出的數(shù)據(jù)量過大(幾十萬(wàn)條數(shù)據(jù)),下載時(shí)間過長(zhǎng),所以用.zip壓縮文件替代excel文件
本人以前也做過導(dǎo)出文件的功能,但是用的方法是后端處理數(shù)據(jù)然后放到另一個(gè)服務(wù)器上,前端要做的就是window.open 打開這個(gè)默認(rèn)地址加返回的地址拼接成的鏈接就可以自動(dòng)下載了
但是現(xiàn)在新入職的這家公司后端老哥明確告訴我:不行!沒辦法了,百度csdn chatgpt搜吧。。。。
經(jīng)過一堆無(wú)用答案和無(wú)數(shù)的坑后終于有了解決辦法,參考https://blog.csdn.net/Amy126/article/details/113882421? 老哥和其他各種老哥的方法
總結(jié):1.在接口處設(shè)置responseType和headers:
export function searchPersonnelHousInfoExport(query) {
return request({
baseUrl: '/api-login',
url: '/miniadmin/personnelHous/searchPersonnelHousInfoExport',
method: 'GET',
params: query,
responseType: 'blob', //注意
headers: { //注意
'Content-Type': 'application/json; application/octet-stream'
}
})
}
2.調(diào)用接口(注意設(shè)置文件格式)
async exportex(){
let postData = {
current: this.currentPage,
size: this.pageSize
}
let res = await searchPersonnelHousInfoExport(postData)
let blob = new Blob([res.data], { type: 'application/zip' }); //設(shè)置下載的內(nèi)容以及格式
const url = window.URL.createObjectURL(blob); //設(shè)置路徑
const link = window.document.createElement('a'); // 創(chuàng)建a標(biāo)簽
link.href = url;
let filename = res.headers['content-disposition']
.split(';')[1]
.split('filename=')[1]
let decodedURL = decodeURIComponent(filename); //解碼,返回的是文件流所以我從res.header里面拿的文件名,但是是編碼后的%E4巴拉巴拉的,所以拿來(lái)用的話要在前端解碼
link.download = decodedURL; //設(shè)置文件名
link.style.display = 'none';
link.click();
console.log(link,'res')
URL.revokeObjectURL(url);
}
3.如果下載下來(lái)是一堆亂碼或解析不了文件,去看看是否在main.js引入了mockjs,非必要就不引入,如果確實(shí)需要就這樣:
?
?
————————————————————分割線————————————————————
摸索過程(出現(xiàn)各種問題的原因,時(shí)間著急的同學(xué)可以跳過):新入職的這個(gè)公司沒弄過這個(gè)東西,所以就得自己下載處理接口返回的文件流,也就是那“一堆亂碼”,當(dāng)時(shí)打印res發(fā)現(xiàn)res.header里有一個(gè)地址,打開發(fā)現(xiàn)能直接下載這個(gè)壓縮文件,心里暗暗竊喜,這不是省事了嗎,結(jié)果清空篩選條件發(fā)現(xiàn)是后端放開了對(duì)token的校驗(yàn),一旦恢復(fù)校驗(yàn)接口馬上就報(bào)錯(cuò)了,而實(shí)際線上環(huán)境這樣做顯然是不安全的,不可能讓后端放開校驗(yàn),而出現(xiàn)這種情況的原因是在原頁(yè)面發(fā)了一次請(qǐng)求,打開新頁(yè)面又發(fā)了一次請(qǐng)求,原頁(yè)面在請(qǐng)求頭中設(shè)置了token,新開的頁(yè)面哪有這個(gè)東西,著急壞了,想著能不能把token跟著參數(shù)一起傳過去,后端校驗(yàn)找不到請(qǐng)求頭中的token去判斷參數(shù)里有沒有token,后端的回答是:所有請(qǐng)求都要先校驗(yàn)有無(wú)token?。?!
?
這就很麻煩了,老老實(shí)實(shí)處理流吧QAQ
各種查各種找,經(jīng)過很多無(wú)用嘗試(當(dāng)磨煉心態(tài)了)結(jié)果得出的結(jié)論:
步驟1:
接口代碼(注意設(shè)置responseType和headers):
export function searchPersonnelHousInfoExport(query) {
return request({
baseUrl: '/api-login',
url: '/miniadmin/personnelHous/searchPersonnelHousInfoExport',
method: 'GET',
params: query,
responseType: 'blob', //注意
headers: { //注意
'Content-Type': 'application/json; application/octet-stream'
}
})
}
步驟2:
調(diào)用接口:
async exportex(){
let postData = {
current: this.currentPage,
size: this.pageSize
}
let res = await searchPersonnelHousInfoExport(postData)
let blob = new Blob([res.data], { type: 'application/zip' }); //設(shè)置下載的內(nèi)容以及格式
const url = window.URL.createObjectURL(blob); //設(shè)置路徑
const link = window.document.createElement('a'); // 創(chuàng)建a標(biāo)簽
link.href = url;
let filename = res.headers['content-disposition']
.split(';')[1]
.split('filename=')[1]
let decodedURL = decodeURIComponent(filename); //解碼,返回的是文件流所以我從res.header里面拿的文件名,但是是編碼后的%E4巴拉巴拉的,所以拿來(lái)用的話要在前端解碼
link.download = decodedURL; //設(shè)置文件名
link.style.display = 'none';
link.click();
console.log(link,'res')
URL.revokeObjectURL(url);
}
結(jié)果:真的下載到了.zip壓縮文件了!興高采烈的打開,結(jié)果傻眼了:能拿到壓縮文件,解壓后卻不是excel文件,當(dāng)時(shí)我的心,拔涼拔涼的啊,但是這邊排期還有不到兩天了,沒辦法,搜解決辦法吧
。。。。。漫長(zhǎng)的一天多。。。。。。
終于在搜的頭暈眼花口吐白沫甚至想到iframe嵌套往里塞地址和請(qǐng)求頭之后找到了一個(gè)不一樣的結(jié)論:mock模塊會(huì)影響原生的ajax請(qǐng)求,使得服務(wù)器返回的blob類型變成亂碼
瞬間虎軀一震,來(lái)到main.js一看:
// 全局 Mock 接口
import './mock'
趕緊試試,立馬把引入注釋了:
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-772183.html
我滴媽啊,終于解決了,當(dāng)時(shí)熱淚盈眶,因?yàn)檫@個(gè)亂碼問題困擾我一天半了,mock火速滾出我的電腦!文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-772183.html
到了這里,關(guān)于前端調(diào)接口下載(導(dǎo)出)后端返回.zip壓縮文件流(的坑?。┑奈恼戮徒榻B完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!