前端很多項(xiàng)目中,都有文件下載的需求,特別是JS生成文件內(nèi)容,然后讓瀏覽器執(zhí)行下載操作(例如在線圖片編輯、在線代碼編輯、iPresst等
但受限于瀏覽器,很多情況下我們都只能給出個(gè)鏈接,讓用戶點(diǎn)擊打開(kāi)-》另存為。如下面這個(gè)鏈接:
用戶點(diǎn)擊這個(gè)鏈接的時(shí)候,瀏覽器會(huì)打開(kāi)并顯示鏈接指向的文件內(nèi)容,顯然,這并沒(méi)有實(shí)現(xiàn)我們的需求。HTML5中給a標(biāo)簽增加了一個(gè)download屬性,只要有這個(gè)屬性,點(diǎn)擊這個(gè)鏈接時(shí)瀏覽器就不在打開(kāi)鏈接指向的文件,而是改為下載(目前只有chrome、firefox和opera支持)。
下載時(shí)會(huì)直接使用鏈接的名字來(lái)作為文件名,但是是可以改的,只要給download加上想要的文件名即可,如:download=“not-a-file.js”。
但是這樣還不夠,以上的方法只適合用在文件是在服務(wù)器上的情況。如果在瀏覽器端js生成的內(nèi)容,想讓瀏覽器進(jìn)行下載要如何辦到呢?
其實(shí)還是有辦法辦到的,相信很多人都多少聽(tīng)過(guò)了DataURI這個(gè)詞,比較常見(jiàn)的就是圖片的src,如:
那么,現(xiàn)在要將js生成的內(nèi)容進(jìn)行下載就有法可依了。封裝成一個(gè)方法如下:
aLink.download = fileName;
aLink.href = "data:text/plain," + content;
}
調(diào)用downloadFile之后,用戶點(diǎn)擊鏈接,就能觸發(fā)瀏覽器下載。
但是,還不夠,上面的辦法有兩個(gè)硬傷,會(huì)導(dǎo)致流失很多懶人美眉:
下載的文件類(lèi)型限制死了,美眉要下載處理后的果照怎么辦?
下載還要再點(diǎn)擊一下,太麻煩啦。
要解決文件類(lèi)型的問(wèn)題,可以用瀏覽器的新API(URL.createObjectURL)來(lái)解決問(wèn)題,URL.createObjectURL通常都是用來(lái)創(chuàng)建圖片的DataURI用來(lái)顯示圖片,這里用來(lái)下載文件,讓瀏覽器來(lái)幫我們?cè)O(shè)定好文件類(lèi)型。
URL.createObjectURL的參數(shù)是File對(duì)象或者Blob對(duì)象,F(xiàn)ile對(duì)象也就是通過(guò)input[type=file]選擇的文件,Blob對(duì)象是二進(jìn)制大對(duì)象,詳細(xì)說(shuō)明可參考這里。
現(xiàn)在,我們只要用content創(chuàng)建一個(gè)ObjectURL并賦值給aLink即可解決文件類(lèi)型的限制問(wèn)題。
文件的自動(dòng)下載也挺好辦,自己構(gòu)建一個(gè)UI點(diǎn)擊事件,再自動(dòng)觸發(fā)下,就能實(shí)現(xiàn)自動(dòng)下載啦。
現(xiàn)在來(lái)看看最終代碼:
var aLink = document.createElement('a');
var blob = new Blob([content]);
var evt = document.createEvent("HTMLEvents");
evt.initEvent("click", false, false);//initEvent 不加后兩個(gè)參數(shù)在FF下會(huì)報(bào)錯(cuò), 感謝 Barret Lee 的反饋
aLink.download = fileName;
aLink.href = URL.createObjectURL(blob);
aLink.dispatchEvent(evt);
}
現(xiàn)在,只要一調(diào)用downloadFile,文件就自動(dòng)下載了
注:目前(2014-01)Blob和URL.createObjectURL在標(biāo)準(zhǔn)瀏覽器里面都不再需要加私有前綴,可以放心使用,如果你不放心,可以查查Can I Use。
更多建議: