一、第一種方式是前端創(chuàng)建超鏈接坠七,通過a標(biāo)簽的鏈接向后端服務(wù)發(fā)get請求或者是window.location.href,接收后端的文件流
const download = (url, fileName) => {
const link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.setAttribute('download', fileName)
document.body.appendChild(link)
link.click()
}
location.href或者是a標(biāo)簽直接指向一個文件的話混稽,瀏覽器會下載該文件召夹,對于單文件下載沒有什么問題,但是如果下載多文件售碳,點擊過快就會重置掉前面的請求强重,href鏈接靜態(tài)資源而且適用于瀏覽器無法識別文件,如果是html贸人、jpg间景、pdf等會直接解析展示,而不會下載
<a >下載文件</a>
window.open可以打開一個新窗口艺智,雖然能通過這種方式下載文件倘要,但是新的窗口不會關(guān)閉,明顯體驗上不好
二十拣、方式通過創(chuàng)建form表單的方式
利用form表單提交能發(fā)起瀏覽器請求封拧,并且也可以作為多文件下載來使用
var params = {// 參數(shù)
id:xx,
name:xx
};
var form = document.createElement('form')
form.id = 'form'
form.name = 'form'
document.body.appendChild (form)
for (var obj in params) {
if (params.hasOwnProperty(obj)) {
var input = document.createElement('input')
input.tpye='hidden'
input.name = obj;
input.value = params[obj]
form.appendChild(input)
}
}
form.method = "GET" //請求方式
form.action = runEnv.api_url+'請求地址'
form.submit()
document.body.removeChild(form)
},
三、會對后端發(fā)的post請求夭问,使用blob格式泽西,后端返回文件二進制流
mdn 上是這樣介紹 Blob 的:
Blob 對象表示一個不可變、原始數(shù)據(jù)的類文件對象缰趋。Blob 表示的不一定是JavaScript原生格式的數(shù)據(jù),axios捧杉,設(shè)置responseType: 'arraybuffer',接收二進制流
axios({
method: 'post',
url: '/export',
responseType: 'arraybuffer',
})
.then(res => {
// 假設(shè) data 是返回來的二進制數(shù)據(jù)
const data = res.data
const url = window.URL.createObjectURL(new Blob([data], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}))
const link = document.createElement('a')
link.style.display = 'none'
link.href = url
const fileNames = res.headers['content-disposition'] // 獲取到Content-Disposition;filename
const regFileNames = decodeURI(fileNames.match(/=(.*)$/)[1])
link.setAttribute('download', regFileNames)
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
})
四、獲取文件下載文件流的實時進度(進度條)
文件下載功能體驗不友好埠胖,特別是下載一些比較耗時的文件糠溜,用戶在頁面上傻等不知道下載的進度是怎么樣的,總以為是系統(tǒng)卡死了,所以需要一個進度顯示
后臺主要是要返回計算好的文件大小直撤,否則上面前端計算進度的時候取的total永遠是0非竿,這個就是一個隱藏的坑。(請求返回頭添加content-length)
image.png
export const dowloadFile = (data, callback) => {
return request({
url: 'file/downloadFile',
method: 'post',
responseType: 'blob',
data: data,
onDownloadProgress (progress) {
callback(progress)
}
})
}
async batchDownloadFile (id) {
this.percentage = 0
this.$refs.FileProgress.progressShow = true
const res = await batchDownloadFile(id, this.processCallback)
if (res.status !== 200) {
this.$message.warning('下載失敗')
this.$refs.FileProgress.progressShow = false // 關(guān)閉進度條顯示層
return false
}
const fileNames = res.headers['content-disposition'] // 獲取到Content-Disposition;filename
const regFileNames = decodeURI(fileNames.match(/=(.*)$/)[1])
const url = window.URL.createObjectURL(new Blob([res.data]))
const link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.setAttribute('download', regFileNames)
document.body.appendChild(link)
link.click()
this.$refs.FileProgress.progressShow = false // 關(guān)閉進度條顯示層
},
processCallback (progressEvent) {
const progressBar = Math.round(progressEvent.loaded / progressEvent.total * 100)
this.percentage = progressBar
},