成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

通過(guò) JavaScript 下載文件到本地(單文件)

Julylovin / 802人閱讀

摘要:最近在做一個(gè)文件下載的功能,這里把做的過(guò)程中用的技術(shù)和坑簡(jiǎn)要總結(jié)下。前端假設(shè)代理服務(wù)接口是后端單文件的處理先寫到這里,多文件的下載下篇在寫。

最近在做一個(gè)文件下載的功能,這里把做的過(guò)程中用的技術(shù)和坑簡(jiǎn)要總結(jié)下。
1. 單文件下載(a標(biāo)簽) 同源單文件

針對(duì)單文件的情況下,同源的文件,可以通過(guò) < a> 標(biāo)簽的 download 屬性下載文件

  const elt = document.createElement("a");
  elt.setAttribute("href", url);
  elt.setAttribute("download", "file.png");
  elt.style.display = "none";
  document.body.appendChild(elt);
  elt.click();
  document.body.removeChild(elt);

但是這個(gè)方案并不適用于非同源的資源,此時(shí)它相當(dāng)于普通的超鏈接,點(diǎn)擊會(huì)跳轉(zhuǎn)到資源頁(yè)面,而不是下載。

非同源圖片

如果不存在CORS問題, 可以借助Blob實(shí)現(xiàn)下載(構(gòu)造xhr請(qǐng)求文件地址, 以Blob的形式接收Response):

function downloadWithBlob(url) {
  fetch(url).then(res => res.blob().then(blob => {
    var a = document.createElement("a");
    var url = window.URL.createObjectURL(blob);
    var filename = "file.png";
    a.href = url;
    a.download = filename;
    a.click();
    window.URL.revokeObjectURL(url);
  }));
}

如果存在CORS問題,可以考慮使用 canvas 將圖片轉(zhuǎn)換成 base64 編碼之后再通過(guò) 標(biāo)簽的 download 屬性下載

function downloadPic(url) {
  const img = new Image;
  const canvas = document.createElement("canvas");
  const ctx = canvas.getContext("2d");
  img.onload = function() {
    canvas.width = this.width;
    canvas.height = this.height;
    ctx.drawImage(this, 0, 0);

    const elt = document.createElement("a");
    elt.setAttribute("href", canvas.toDataURL("image/png"));
    elt.setAttribute("download", "file.png");
    elt.style.display = "none";
    document.body.appendChild(elt);
    elt.click();
    document.body.removeChild(elt);
  };
  img.crossOrigin = "anonymous";
  img.src = url;
}
2. 單文件下載(iframe)

iframe方式是在頁(yè)面內(nèi)隱藏iframe, 然后將下載地址加載到iframe中, 從而觸發(fā)瀏覽器的下載行為

  const iframe = document.createElement("iframe");
  iframe.src = url;
  iframe.style.display = "none";
  document.body.appendChild(iframe);

但是這里發(fā)現(xiàn),即使是同域的圖片,也無(wú)法完成下載,這是為啥呢?

這里就有個(gè)上面的a鏈接下載沒有提到的問題:什么樣的鏈接才能觸發(fā)瀏覽器的下載:

url如何觸發(fā)瀏覽器自動(dòng)下載

一個(gè)url能否觸發(fā)瀏覽器自動(dòng)下載,主要看該請(qǐng)求響應(yīng)頭response header是否滿足,一般是看Content-DispositionContent-Type這兩個(gè)消息頭:

response header中指定了Content-Disposition為attachment,它表示讓瀏覽器把消息體以附件的形式下載并保存到本地 (一般還會(huì)指定filename, 下載的文件名默認(rèn)就是filename)

response header中指定了Content-Type 為 application/octet-stream(無(wú)類型) 或 application/zip(zip包時(shí))等等。(其中 application/octet-stream表示http response為二進(jìn)制流(沒指定明確的type), 用在未知的應(yīng)用程序文件,瀏覽器一般不會(huì)自動(dòng)執(zhí)行或詢問執(zhí)行。瀏覽器會(huì)像對(duì)待 設(shè)置了HTTP頭Content-Disposition 值為 attachment 的文件一樣來(lái)對(duì)待這類文件)

只要url滿足上述觸發(fā)的要求,那么都可以通過(guò)iframe的形式來(lái)下載

3. 代理服務(wù)處理下載

如果后端自己也能控制的話,或者后端能配合的話,可以寫一個(gè)代理服務(wù),在后端去請(qǐng)求文件數(shù)據(jù),然后設(shè)置好相應(yīng)的response header, 然后前端請(qǐng)求代理服務(wù)來(lái)做下載。

前端(假設(shè)代理服務(wù)接口是http://exampale.com/download):

  const downloadUrl = "http://exampale.com/download?url=" + encodeURIComponent(url) + "&name=xxx";
  const elt = document.createElement("a");
  elt.setAttribute("href", downloadUrl);
  elt.setAttribute("download", "file.png");
  ... 

后端

const url = decodeURIComponent(req.query.url);
http.get(url, (response) => {
  res.setHeader("Content-disposition", "attachment;filename=" + req.query.name);
  res.setHeader("Content-type", "application/octet-stream");
  response.pipe(res);
});

單文件的處理先寫到這里,多文件的下載下篇在寫。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/102517.html

相關(guān)文章

  • 通過(guò) Node 批量下載文件本地(多文件

    摘要:包批量下載雖然說(shuō)可以遍歷所有文件,然后去批量下載單個(gè)文件,但是這種體驗(yàn)畢竟不太好,最常見的做法是把批量的文件下載并打包到中。 最近在做一個(gè)文件下載的功能,這里把做的過(guò)程中用的技術(shù)和坑簡(jiǎn)要總結(jié)下。上篇文章《通過(guò) JavaScript 下載文件到本地(單文件)》說(shuō)了下如何下載單文件,這篇主要說(shuō)下如何做多文件的批量下載 多文件分別處理 如果文件數(shù)量可控,對(duì)于下載出來(lái)的文件格式無(wú)要求,可以用最...

    plus2047 評(píng)論0 收藏0
  • nodejs 基礎(chǔ)篇整合

    摘要:基礎(chǔ)篇整合最近有朋友也想學(xué)習(xí)相關(guān)方面的知識(shí),如果你是后端想接近前端,作為一門跑在服務(wù)端的語(yǔ)言從這里入門再好不過(guò)了。事件驅(qū)動(dòng)機(jī)制是通過(guò)內(nèi)部單線程高效率地維護(hù)事件循環(huán)隊(duì)列來(lái)實(shí)現(xiàn)的,沒有多線程的資源占用和上下文的切換。 nodeJs 基礎(chǔ)篇整合 最近有朋友也想學(xué)習(xí)nodeJs相關(guān)方面的知識(shí),如果你是后端想接近前端,node作為一門跑在服務(wù)端的JS語(yǔ)言從這里入門再好不過(guò)了。如果你正好喜歡前端,...

    lemanli 評(píng)論0 收藏0
  • nodejs 基礎(chǔ)篇整合

    摘要:基礎(chǔ)篇整合最近有朋友也想學(xué)習(xí)相關(guān)方面的知識(shí),如果你是后端想接近前端,作為一門跑在服務(wù)端的語(yǔ)言從這里入門再好不過(guò)了。事件驅(qū)動(dòng)機(jī)制是通過(guò)內(nèi)部單線程高效率地維護(hù)事件循環(huán)隊(duì)列來(lái)實(shí)現(xiàn)的,沒有多線程的資源占用和上下文的切換。 nodeJs 基礎(chǔ)篇整合 最近有朋友也想學(xué)習(xí)nodeJs相關(guān)方面的知識(shí),如果你是后端想接近前端,node作為一門跑在服務(wù)端的JS語(yǔ)言從這里入門再好不過(guò)了。如果你正好喜歡前端,...

    lentrue 評(píng)論0 收藏0
  • nodejs 基礎(chǔ)篇整合

    摘要:基礎(chǔ)篇整合最近有朋友也想學(xué)習(xí)相關(guān)方面的知識(shí),如果你是后端想接近前端,作為一門跑在服務(wù)端的語(yǔ)言從這里入門再好不過(guò)了。事件驅(qū)動(dòng)機(jī)制是通過(guò)內(nèi)部單線程高效率地維護(hù)事件循環(huán)隊(duì)列來(lái)實(shí)現(xiàn)的,沒有多線程的資源占用和上下文的切換。 nodeJs 基礎(chǔ)篇整合 最近有朋友也想學(xué)習(xí)nodeJs相關(guān)方面的知識(shí),如果你是后端想接近前端,node作為一門跑在服務(wù)端的JS語(yǔ)言從這里入門再好不過(guò)了。如果你正好喜歡前端,...

    高勝山 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<