vue實(shí)現(xiàn)文件下載勋眯、導(dǎo)出、前端多種方式實(shí)現(xiàn)文件下載

前端開(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ù)覽呵燕,那么這種文件要下載的解決方式:



舉個(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ù)文件流格式如圖:

image.jpeg

參考這個(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?
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市惭缰,隨后出現(xiàn)的幾起案子浪南,更是在濱河造成了極大的恐慌,老刑警劉巖漱受,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件络凿,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡昂羡,警方通過(guò)查閱死者的電腦和手機(jī)絮记,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)虐先,“玉大人到千,你說(shuō)我怎么就攤上這事「八耄” “怎么了憔四?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)般眉。 經(jīng)常有香客問(wèn)我了赵,道長(zhǎng),這世上最難降的妖魔是什么甸赃? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任柿汛,我火速辦了婚禮,結(jié)果婚禮上埠对,老公的妹妹穿的比我還像新娘络断。我一直安慰自己,他們只是感情好项玛,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布貌笨。 她就那樣靜靜地躺著,像睡著了一般襟沮。 火紅的嫁衣襯著肌膚如雪锥惋。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,370評(píng)論 1 302
  • 那天开伏,我揣著相機(jī)與錄音膀跌,去河邊找鬼。 笑死固灵,一個(gè)胖子當(dāng)著我的面吹牛捅伤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播巫玻,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼丛忆,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼困介!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起蘸际,我...
    開(kāi)封第一講書(shū)人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎徒扶,沒(méi)想到半個(gè)月后粮彤,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡姜骡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年导坟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片圈澈。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡惫周,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出康栈,到底是詐尸還是另有隱情递递,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布啥么,位于F島的核電站登舞,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏悬荣。R本人自食惡果不足惜菠秒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望氯迂。 院中可真熱鬧践叠,春花似錦、人聲如沸嚼蚀。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)轿曙。三九已至匾二,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間拳芙,已是汗流浹背察藐。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留舟扎,地道東北人分飞。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像睹限,于是被迫代替她去往敵國(guó)和親譬猫。 傳聞我的和親對(duì)象是個(gè)殘疾皇子讯檐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容