公共Hooks封裝文件下載useDownloadFile實例詳解
引言
對于經(jīng)常需要開發(fā)企業(yè)管理后臺的前端開發(fā)來說,必不可少的需要使用表格對于數(shù)據(jù)進行操作,在對于現(xiàn)有項目進行代碼優(yōu)化時,封裝一些公共的Hooks.
本篇文章為useDownloadFile.js
基于個人項目環(huán)境進行封裝的Hooks,僅以本文介紹封裝Hooks思想心得,故相關(guān)代碼可能不適用他人
項目環(huán)境
Vue3.x + Ant Design Vue3.x + Vite3.x
對于企業(yè)管理后臺中常見的各類資源文件(圖片、文檔、音視頻等),下載保存本地則是再正常不過的需求了,為保證統(tǒng)一性和避免每個單頁面文件內(nèi)重復(fù)書寫冗余代碼,封裝此方法
封裝前提:各方法對比
方法 | 操作原理 | 優(yōu)點 | 缺點 |
---|---|---|---|
form 表單 | 動態(tài)生成一個表單,利用表單提交的功能來實現(xiàn)文件的下載 | 兼容性好,不會出現(xiàn)URL長度限制問題 | 無法知道下載的進度,用戶體驗交互差 無法直接下載瀏覽器可直接預(yù)覽的文件類型 |
window.open / location.href | 打開新標(biāo)簽頁訪問下載資源 | 簡單粗暴 | 會出現(xiàn)URL長度限制問題 無法知道下載的進度,用戶體驗交互差 無法直接下載瀏覽器可直接預(yù)覽的文件類型 需要注意url編碼問題 不能添加header,也就不能進行鑒權(quán) |
<a /> download 屬性 | 利用a標(biāo)簽原生訪問屬性,附加新增的download屬性,使用瀏覽器進行下載 | 簡單粗暴且可下載正常預(yù)覽文件 | 不能下載跨域地址文件 IE/Edge內(nèi)兼容問題 無法鑒權(quán) |
Blob 對象 | 發(fā)請求獲取二進制數(shù)據(jù),轉(zhuǎn)化為Blob對象,利用URL.createObjectUrl生成url地址,賦值在a標(biāo)簽的href屬性上,結(jié)合download進行下載 | 能解決不能直接下載瀏覽器可瀏覽的文件 可以鑒權(quán) | IE10以下不可用 Safari使用情況可能有問題 |
綜上并結(jié)合實際項目,最后使用Blob對象進行封裝下載文件方法
封裝分解:下載核心代碼
xhr.onloadend = function (e) { if (e.target.status === 200 || e.target.status === 304) { const aElement = document.createElement('a'); const blob = e.target.response; const url = window.URL.createObjectURL(blob); aElement.style.display = 'none'; aElement.href = url; aElement.download = `${options.fileName}.${fileType}`; document.body.appendChild(aElement); aElement.click(); if (window.URL) { window.URL.revokeObjectURL(blob); } else { window.webkitURL.revokeObjectURL(blob); } document.body.removeChild(aElement); } }; xhr.send();
封裝分解:用戶體驗設(shè)計
- 下載過程中,配合項目使用的Ant Design Vue框架,可以加強用戶感知文件下載進度,
- 為防止用戶暴力點擊,重復(fù)觸發(fā)下載的問題,使用Loading Flag標(biāo)識,
- 下載失敗后,提示用戶,重新下載
createVNode('div', {}, ['文件下載過程中請勿關(guān)閉當(dāng)前頁面']), createVNode('div', { className: 'mt-2' }, [`當(dāng)前下載進度 ${progress.value}%`]), catch (e) { console.error(e); downloading = false; infoModal && infoModal.destroy(); Modal.error({ title: '提示', content: '下載發(fā)生異常,請重試', }); }
useDownloadFile.js完整代碼
import { createVNode, ref, onBeforeUnmount } from 'vue'; import { Modal } from 'ant-design-vue'; export function useDownloadFile() { let xhr = null; let downloading = false; // 限制同一文件同時觸發(fā)多次下載 let infoModal; onBeforeUnmount(() => { xhr && xhr.abort(); }); const downloadFile = options => { try { if (downloading || !options.url || !options.fileName) return; downloading = true; options.url = options.url.replace('http://', 'https://'); const progress = ref(0); const fileType = options.url.split('.').pop(); xhr = new XMLHttpRequest(); xhr.responseType = 'blob'; xhr.open('get', options.url, true); infoModal = Modal.info({ title: '文件下載', okText: '取消下載', content: () => { return createVNode('div', {}, [ createVNode('div', {}, ['文件下載過程中請勿關(guān)閉當(dāng)前頁面']), createVNode('div', { className: 'mt-2' }, [`當(dāng)前下載進度 ${progress.value}%`]), ]); }, onOk() { xhr.abort(); return Promise.resolve(); }, }); xhr.onprogress = function (e) { progress.value = Math.floor((e.loaded / e.total) * 100); if (progress.value === 100) { downloading = false; infoModal.destroy(); } }; xhr.onloadend = function (e) { if (e.target.status === 200 || e.target.status === 304) { const aElement = document.createElement('a'); const blob = e.target.response; const url = window.URL.createObjectURL(blob); aElement.style.display = 'none'; aElement.href = url; aElement.download = `${options.fileName}.${fileType}`; document.body.appendChild(aElement); aElement.click(); if (window.URL) { window.URL.revokeObjectURL(blob); } else { window.webkitURL.revokeObjectURL(blob); } document.body.removeChild(aElement); } }; xhr.send(); } catch (e) { console.error(e); downloading = false; infoModal && infoModal.destroy(); Modal.error({ title: '提示', content: '下載發(fā)生異常,請重試', }); } }; return { downloadFile, }; }
以上就是公共Hooks封裝文件下載useDownloadFile實例詳解的詳細內(nèi)容,更多關(guān)于公共Hooks封裝文件下載的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue項目根據(jù)不同環(huán)境進行設(shè)置打包命令的方法
這篇文章主要介紹了vue項目根據(jù)不同環(huán)境進行設(shè)置打包命令,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-11-11vue2之響應(yīng)式雙向綁定,在對象或數(shù)組新增屬性頁面無響應(yīng)的情況
這篇文章主要介紹了vue2之響應(yīng)式雙向綁定,在對象或數(shù)組新增屬性頁面無響應(yīng)的情況及解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04