前端開(kāi)發(fā)中下梢,經(jīng)常遇到文件下載的功能客蹋。這里對(duì)常見(jiàn)的文件下載方式做一些總結(jié)。
前端下載通常分為兩種情形怔球,一種是后端直接給一個(gè)文件地址嚼酝,通過(guò)瀏覽器打開(kāi)就可以下載浮还,另外一種則需要發(fā)送請(qǐng)求竟坛,后端返回二進(jìn)制流數(shù)據(jù),前端解析流數(shù)據(jù),生成URL担汤,實(shí)現(xiàn)下載涎跨。
一、后端直接返回文件路徑進(jìn)行下載
1崭歧、普通文件地址
情況1隅很、直接下載 - 針對(duì)一些瀏覽器無(wú)法識(shí)別的文件格式
針對(duì)一些瀏覽器無(wú)法識(shí)別的文件格式(如pdf、xls率碾、ppt)叔营。可以直接在地址欄上輸入U(xiǎn)RL即可觸發(fā)瀏覽器的下載功能所宰。
* 地址欄輸入文件URL
* window.location.href = URL
* window.open(URL)
該方式將下載邏輯放在后端處理绒尊,后端給出固定的url,前端使用window.location.herf下載
路徑可以是相對(duì)路徑也可以是絕對(duì)路徑
情況2仔粥、直接下載 (使用a標(biāo)簽download屬性)
直接下載僅支持使用的瀏覽器無(wú)法識(shí)別的文件婴谱。如果是瀏覽器支持的文件格式(如:html、jpg躯泰、png谭羔、mp4、mp3)等麦向。則不會(huì)觸發(fā)文件下載瘟裸,而是被瀏覽器直接觸發(fā)解析展示。
針對(duì)這種情況磕蛇,我們可以使用a標(biāo)簽的download屬性景描,可以設(shè)置成文件的文件名。
<a :href="scope.row.vPath" :download="scope.row.vName" class="downloadBtn">
<el-button type="text">{{ $t("message.work.Download") }}</el-button>
</a>
2秀撇、OSS存儲(chǔ)方式的文件地址
這種方式的文件地址被訪問(wèn)時(shí)超棺,訪問(wèn)文件路徑默認(rèn)是下載還是預(yù)覽跟后端設(shè)置的服務(wù)器配置有關(guān)。
如果訪問(wèn)oss地址的文件只能預(yù)覽呵燕,那么這種文件要下載的解決方式:
- 改為請(qǐng)求接口得到流的方式下載(可能面臨大文件時(shí)接口請(qǐng)求時(shí)間非常長(zhǎng)的問(wèn)題)
- 直接訪問(wèn)文件地址棠绘,在地址后添加參數(shù) ?response-content-type=application%2Foctet-stream
例如:https://XXX.XX.XXX:5443/alibaba/16583705678118fad71ee6fad4bcfb91a9cafb8335800.mp4?response-content-type=application%2Foctet-stream
舉個(gè)例子:
在阿里云 oss 通過(guò)鏈接下載文件 而不是 直接打開(kāi)鏈接文件 在頁(yè)面中顯示
通過(guò) a 標(biāo)簽下載 oss 中的文件,需要在連接的后面添加 response-content-type=application/octet-stream 的參數(shù) 就可以直接下載了
<a target="_blank" download="" ></a>
二再扭、通過(guò)后端接口返回流氧苍,前端對(duì)流進(jìn)行文件預(yù)覽 or 文件下載
通過(guò)接口的方式,前端首先要將接口的返回頭設(shè)置為blob方式泛范,然后解析二進(jìn)制流
具體實(shí)現(xiàn)步驟:
1让虐、axios 設(shè)置響應(yīng)頭 responseType: 'blob',
export function downloadExcelApi(data) {
return request({
url: prefix + `/member/download/template/?tenantCode=${data.tenantCode}`,
method: 'get',
responseType: 'blob', // 這里相應(yīng)的要在request接收
data
});
}
這里可以在axios攔截器中設(shè)置d1響應(yīng)頭,可以設(shè)置 延長(zhǎng)超時(shí)時(shí)間罢荡、加載動(dòng)畫(huà)赡突,例如:
const service = axios.create({
baseURL: config.BASE_API, //
timeout: 30000 // 請(qǐng)求超時(shí)
});
service.interceptors.request.use(
(config) => {
var xtoken = localStorage.getItem('loginToken');
if (xtoken != null) {
config.headers['X-User'] = xtoken;
config.headers['System'] = 'M';
config.headers['crmversion'] = 'V1.0.0';
config.headers['channel'] = 'PC';
config.headers['Content-Type'] = 'application/json';
}
if (config.responseType === 'blob') {
config.timeout = 60000;
loadingInstance = Loading.service({
lock: true,
text: 'Loading',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
}
// ....................
})
service.interceptors.response.use(
(response) => {
if (response.config.responseType === 'blob') {
// 下載時(shí)直接返回blob
loadingInstance && loadingInstance.close();
return response.data;
}
// ................
})
解析二進(jìn)制流对扶,下載和預(yù)覽是兩種不同的處理:
處理1:請(qǐng)求后的二進(jìn)制流轉(zhuǎn)為下載文件
// 根據(jù)路徑下載文件流
fileDown(row) {
console.log('根據(jù)路徑下載文件流', this.url(row.signDocumentPath) , row.documentName)
const params={
filePath: this.url(row.signDocumentPath),
}
API_Audit.downloadFile(params).then((res)=>{
const url = window.URL.createObjectURL(new Blob([res]))
const name = `${row.documentName}`
const link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.setAttribute('download', name)
document.body.appendChild(link)
link.click()
})
},
const res = await this.$api.user.downloadExcelApi({ tenantCode: tenantInfo.code })
const url = window.URL.createObjectURL(new Blob([res]))
const name = '用戶導(dǎo)入模板.xlsx'
const link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.setAttribute('download', name)
document.body.appendChild(link)
link.click()
處理2:請(qǐng)求后的blob轉(zhuǎn)為文件預(yù)覽
const blob = new Blob([res], { type: 'application/pdf;chartset=UTF-8' })
const r = new FileReader();
r.readAsText(blob);
const url = window.URL.createObjectURL(blob)
window.open(url);
后臺(tái)返回的二進(jìn)制數(shù)據(jù)文件流格式如圖:
參考這個(gè)樣子
PK????}?S?_rels/.rels???J?1??_%??m??i??????????&????oo??l?B???|??I????R?9?XV5(
?]?Z?????=?,?????@`?n?/4?????1???@'???ζ#???H?t?N???????-?U]??????L?s???-A?1?$??Q?p????`K?3?%??4??G??OAf?O&@??~]????e?c??MB??[ē@Iz??nf?,'????G???
~S/????:da??+?PO????|?PK?{<?$???PK????}?S?[Content_Types].xml?T?n?0?????*6?PU??C??????\{C,???P??n?TJ%*??ǚ??(?h?v?ZA?&??
??U?U?????6{?oY?Qz-m??0??d<?m"?F}nX?????'3??<!mHN"m?\D??r??z0??*x??5??l<z?V.-V???t?d??(??J?????w?<?-????????5?lOChf????~Os/?K2???-??Q??Z:??Ыj(luò)?uLDLh`?s*?>KG???SB? i~??W-*$8?'??wZ????q?zN???H?;t??N&Я??M??cm????s?????P?s:#}?p??????4?P?????!,.??;??????EY?{??g6??PK?G??R?
?PK????}?S?docProps/app.xml??AN?0?E????uR!?"???B???k?LZK?m?CT8??X q?6p?@??'UK
???????F??US??|???4?'??Q??f??????N??/?u?QC ? 9]"???????0?c?'????X???U???[u?A6I???+?SB9r?@?N?Z?ohiU??.?7.? ~?\???x??,f????????a????,??A?????ZO????N(???????ki??m??????????]\????u???H{C??F??z?p???pV????????g??????_|?M????w?/PK??q?P??"?PK????}?S?docProps/core.xml???N?0?E?%?>???TV??A]Q ? ?;?~m-?A?!?SX????Nh?@????????r?Wm???K?+?g?%???Ro+t???J|`Z??h??6hY??Rn?\9c?? >???)???`)??@1?E????8?B<?-????-???9V??`???????H?G?}t???C?
t?8?r??hv ?^??(j@?E????g??g^?D?q?????\???oE0?a??6x?Q?C???j??G?h??]-??????M?d|?3\ù?v?????:???[??0??n:5Dm
?[5?X??* ;?u_[w??A?]m2(?|?i?c{?1?g?gD?????`pA?=1h???h??J???L?y?=?).??VT?+\O?,????s????l???4????????j??V??PK??()?????PK?????}?S{<?$????_rels/.relsPK?????}?SG??R?
??*?[Content_Types].xmlPK?????}?S?q?P??"????docProps/app.xmlPK?????}?SU?~?7?3????docProps/core.xmlPK?????}?S?E6????????docProps/custom.xmlPK?????}?S7l]????????xl/sharedStrings.xmlPK?????}?S?g?OYwO
. xl/styles.xmlPK?????}?Se4????????xl/theme/theme1.xmlPK?????}?S?a!p???????xl/workbook.xmlPK?????}?S???!????h?xl/_rels/workbook.xml.relsPK?????}?S?()????????xl/worksheets/sheet1.xmlPK??????Y?