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

資訊專欄INFORMATION COLUMN

如何用 JavaScript 下載文件

Scliang / 3150人閱讀

摘要:然而事實(shí)上下載的的確確發(fā)生了,只是要等到下載完文件之后才能構(gòu)建對(duì)象,再轉(zhuǎn)化成文件。權(quán)限校驗(yàn)有些時(shí)候,我們需要對(duì)下載做一些限制,最常見(jiàn)的就是權(quán)限校驗(yàn)了,如檢查該用戶是否有下載的權(quán)限,是否有高速下載的權(quán)限等等。

簡(jiǎn)介

我們知道,下載文件是一個(gè)非常常見(jiàn)的需求,但由于瀏覽器的安全策略的限制,我們通常只能通過(guò)一個(gè)額外的頁(yè)面,訪問(wèn)某個(gè)文件的 url 來(lái)實(shí)現(xiàn)下載功能,但是這種用戶體驗(yàn)非常不好。
幸好,HTML 5 里面為 標(biāo)簽添加了一個(gè) download 的屬性,我們可以輕易的利用它來(lái)實(shí)現(xiàn)下載功能,再也不需要用以前的笨辦法了。

原理

我們先看看 download 的使用方法:

Download file

看看上面的代碼,只要為 標(biāo)簽添加 download 屬性,我們點(diǎn)擊這個(gè)鏈接的時(shí)候就會(huì)自動(dòng)下載文件了~
順便說(shuō)下,download 的屬性值是可選的,它用來(lái)指定下載文件的文件名。像上面的例子中,我們下載到本地的文件名就會(huì)是 filename.zip 拉,如果不指定的話,它就會(huì)是 somefile.zip 這個(gè)名字拉!

看到這里,你可能會(huì)說(shuō),坑爹啊,這明明是用 HTML 5 的新特性來(lái)實(shí)現(xiàn)下載文件嘛,說(shuō)好的用 JavaScript 下載文件呢?

事實(shí)上,用 JavaScript 來(lái)下載文件也是利用這一特性來(lái)實(shí)現(xiàn)的,我們的 JavaScript 代碼不外乎就是:

用 JavaScript 創(chuàng)建一個(gè)隱藏的 標(biāo)簽

設(shè)置它的 href 屬性

設(shè)置它的 download 屬性

用 JavaScript 來(lái)觸發(fā)這個(gè)它的 click 事件

翻譯成 JavaScript 代碼就是:

var a = document.createElement("a");
var url = window.URL.createObjectURL(blob);
var filename = "what-you-want.txt";
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);

好拉,是不是看到有個(gè)陌生的東東呢?

window.URL

window.URL 里面有兩個(gè)方法:

createObjectURL 用 blob 對(duì)象來(lái)創(chuàng)建一個(gè) object URL(它是一個(gè) DOMString),我們可以用這個(gè) object URL 來(lái)表示某個(gè) blob 對(duì)象,這個(gè) object URL 可以用在 hrefsrc 之類的屬性上。

revokeObjectURL 釋放由 createObjectURL 創(chuàng)建的 object URL,當(dāng)該 object URL 不需要的時(shí)候,我們要主動(dòng)調(diào)用這個(gè)方法來(lái)獲取最佳性能和內(nèi)存使用。

知道了這兩個(gè)方法之后,我們?cè)倩厝タ纯瓷厦娴睦泳秃苋菀桌斫饬税?!只是?blob 對(duì)象來(lái)創(chuàng)建一條 URL,然后讓 標(biāo)簽引用該 URL,然后觸發(fā)個(gè)點(diǎn)擊事件,就可以下載文件了!

那么問(wèn)題來(lái)了,blob 對(duì)象哪里來(lái)?

Blob 對(duì)象

Blob 全稱是 Binary large object,它表示一個(gè)類文件對(duì)象,可以用它來(lái)表示一個(gè)文件。根據(jù) MDN 上面的說(shuō)法,File API 也是基于 blob 來(lái)實(shí)現(xiàn)的。

由于本文的主題是講 JavaScript 下載文件,那我們構(gòu)建 blob 的方式就是通過(guò)服務(wù)器返回的文件來(lái)創(chuàng)建 blob 拉!
而最簡(jiǎn)單的方式就是用 fetch API 了,我們可以整合上面的例子:

fetch("http://somehost/somefile.zip").then(res => res.blob().then(blob => {
    var a = document.createElement("a");
    var url = window.URL.createObjectURL(blob);
    var filename = "myfile.zip";
    a.href = url;
    a.download = filename;
    a.click();
    window.URL.revokeObjectURL(url);
}))

很簡(jiǎn)單對(duì)吧!

你可能會(huì)問(wèn),何必這么麻煩呢?直接寫(xiě)成下面這樣不就好了:

Download file

嗯,對(duì)于這種寫(xiě)法,我只能說(shuō),你做的太正確了!如果你要下載的是已經(jīng)存在服務(wù)器上面的靜態(tài)文件的話,那么寫(xiě)成這樣是最方便的。瀏覽器會(huì)幫你處理整個(gè)下載過(guò)程,不需要你干涉。如果你用 blob 的方式來(lái)下載文件的話,會(huì)有下面這些限制的:

限制一:不同瀏覽器對(duì) blob 對(duì)象有不同的限制

具體看看下面這個(gè)表格(出自 FileSaver.js):

Browser Constructs as Filenames Max Blob Size Dependencies
Firefox 20+ Blob Yes 800 MiB None
Firefox < 20 data: URI No n/a Blob.js
Chrome Blob Yes 500 MiB None
Chrome for Android Blob Yes 500 MiB None
Edge Blob Yes ? None
IE 10+ Blob Yes 600 MiB None
Opera 15+ Blob Yes 500 MiB None
Opera < 15 data: URI No n/a Blob.js
Safari 6.1+* Blob No ? None
Safari < 6 data: URI No n/a Blob.js
限制二:構(gòu)建完 blob 對(duì)象后才會(huì)轉(zhuǎn)換成文件

這一點(diǎn)限制對(duì)小文件(幾十kb)可能沒(méi)什么影響,但對(duì)稍微大一點(diǎn)的文件影響就很大了。試想,用戶要下載一個(gè) 100mb 的文件,如果他點(diǎn)擊了下載按鈕之后沒(méi)看到下載提示的話,他肯定會(huì)繼續(xù)按,等他按了幾次之后還沒(méi)看到下載提示時(shí),他就會(huì)抱怨我們的網(wǎng)站,然后離開(kāi)了。

然而事實(shí)上下載的的確確發(fā)生了,只是要等到下載完文件之后才能構(gòu)建 blob 對(duì)象,再轉(zhuǎn)化成文件。而且,用戶再觸發(fā)多幾次下載就會(huì)造成一些資源上的浪費(fèi)。

因此,如果是要下載大文件的話,還是推薦直接創(chuàng)建一個(gè) 標(biāo)簽拉~
寫(xiě) html 也好,寫(xiě) JavaScript 動(dòng)態(tài)創(chuàng)建也好,用自己喜歡的方式去創(chuàng)建就好了。

為什么要用 JavaScript 下載文件

好拉,說(shuō)了半天,其實(shí)我們一直說(shuō)的都是:「不要用 JavaScript 下載文件拉,限制多多,又不好用,直接用 html 就好拉,簡(jiǎn)單方便又快捷」這個(gè)論調(diào)。
事實(shí)上也確實(shí)如此,但有些時(shí)候我們確實(shí)需要通過(guò) JavaScript 來(lái)做一些預(yù)處理。

權(quán)限校驗(yàn)

有些時(shí)候,我們需要對(duì)下載做一些限制,最常見(jiàn)的就是權(quán)限校驗(yàn)了,如檢查該用戶是否有下載的權(quán)限,是否有高速下載的權(quán)限等等。這時(shí)候,我們可以利用 JavaScript 做一些預(yù)處理。如:

fetch("http://somehost/check-permission", options).then(res => {
    if (res.code === 0) {
        var a = document.createElement("a");
        var url = res.data.url;
        var filename = "myfile.zip";
        a.href = url;
        a.download = filename;
        a.click();
    } else {
        alert("You have no permission to download the file!");
    }
});

在這個(gè)例子里面,我們沒(méi)有用 blob 來(lái)構(gòu)建 URL,而是通過(guò)后端服務(wù)器來(lái)計(jì)算出用戶的下載鏈接,然后再利用之前提到的動(dòng)態(tài)創(chuàng)建 標(biāo)簽的方式來(lái)實(shí)現(xiàn)下載,很簡(jiǎn)單吧!

動(dòng)態(tài)文件

動(dòng)態(tài)生成文件然后返回給客戶端也是一個(gè)很常見(jiàn)的需求,譬如我們有時(shí)候需要做導(dǎo)出數(shù)據(jù)的功能,把數(shù)據(jù)庫(kù)中的某些數(shù)據(jù)導(dǎo)出到 Excel 中,然后再返回客戶端。
這時(shí)候我們就不能簡(jiǎn)單的指定 href 屬性,因?yàn)閷?duì)應(yīng)的 URL 并不存在。
我們只能通過(guò) JavaScript 對(duì)服務(wù)器發(fā)出一個(gè)請(qǐng)求,通知它去生成某個(gè)文件,然后把對(duì)應(yīng)的 URL 返回給客戶端。
有沒(méi)有感覺(jué)這個(gè)過(guò)程和上面「權(quán)限校驗(yàn)」一節(jié)很像?肯定拉,因?yàn)槲覀冎皇菍?duì) URL 做了一些預(yù)處理而已嘛~

注意事項(xiàng)

由于 download 屬性是 HTML 5 的新特性,因此它不支持舊版本的瀏覽器。

總結(jié)

HTML 5 新的 download 特性真的很好用,結(jié)合 JavaScript 的動(dòng)態(tài)能力我們可以很方便的做出復(fù)雜的下載功能~

出處

http://scarletsky.github.io/2016/07/03/download-file-using-javascript/

參考資料

https://github.com/eligrey/FileSaver.js/blob/master/FileSaver.js
https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL
https://developer.mozilla.org/en-US/docs/Web/API/Blob
http://stackoverflow.com/questions/19327749/javascript-blob-filename-without-link
http://stackoverflow.com/questions/24501358/how-to-set-a-header-for-a-http-get-request-and-trigger-file-download
http://blog.bguiz.com/2014/07/03/file-download-with-http-request-header/

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

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

相關(guān)文章

  • 何用webpack打包umd模塊并測(cè)試打包結(jié)果

    摘要:對(duì)于的模塊而言可以用來(lái)基于瀏覽器或服務(wù)端的包下面讓我們學(xué)習(xí)如何使用生成首先需要全局安裝讓我們先來(lái)創(chuàng)建一個(gè)用來(lái)返回兩數(shù)之和的加法模塊接下來(lái)我們來(lái)建立配置接下來(lái)使用來(lái)你的模塊現(xiàn)在你可以來(lái)使用這三種不同的方式來(lái)測(cè)試你的包是否正確了在測(cè)試之前需要 對(duì)于 JavaScript 的模塊而言, webpack 可以用來(lái)build 基于瀏覽器或服務(wù)端的包. 下面讓我們學(xué)習(xí)如何使用webpack生成UM...

    guqiu 評(píng)論0 收藏0
  • 回到基礎(chǔ):何用原生 DOM API 生成表格

    摘要:接下來(lái)該填表了生成行和單元格為了填充表格可以遵循同樣的方法,但這次我們需要迭代數(shù)組中的每個(gè)對(duì)象。對(duì)于每個(gè)對(duì)象,我們可以使用生成單元格。 翻譯:瘋狂的技術(shù)宅原文:https://www.valentinog.com/bl... 本文首發(fā)微信公眾號(hào):jingchengyideng歡迎關(guān)注,每天都給你推送新鮮的前端技術(shù)文章 怎樣用原生 JavaScript 生成表格需?本文告訴你答案!...

    Sunxb 評(píng)論0 收藏0
  • 何用 ANTLR 4 實(shí)現(xiàn)自己的腳本語(yǔ)言?

    摘要:是一個(gè)實(shí)現(xiàn)的詞法語(yǔ)法分析生成程序,目前最新版本為,支持,,等語(yǔ)言,這里我們用來(lái)實(shí)現(xiàn)一個(gè)自己的腳本語(yǔ)言。在實(shí)現(xiàn)時(shí),只要每個(gè)節(jié)點(diǎn)都做好自己的工作就可以了。不過(guò),它是一個(gè)好的開(kāi)始,可以讓我們?cè)诖嘶A(chǔ)上,設(shè)計(jì)更完善易用的語(yǔ)言。 ANTLR 是一個(gè) Java 實(shí)現(xiàn)的詞法/語(yǔ)法分析生成程序,目前最新版本為 4.5.2,支持 Java,C#,JavaScript 等語(yǔ)言,這里我們用 ANTLR 4....

    scwang90 評(píng)論0 收藏0

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

0條評(píng)論

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