純JS生成並下載各種文字檔案或圖片

張鑫旭發表於2018-10-25

本文轉載自:www.zhangxinxu.com/wordpress/?…

一、HTML與檔案下載

如果希望在前端側直接觸發某些資源的下載,最方便快捷的方法就是使用HTML5原生的download屬性,例如:

<a href="large.jpg" download>下載</a>複製程式碼

具體介紹可參考我之前的文章:“瞭解HTML/HTML5中的download屬性”。

但顯然,如果純粹利用HTML屬性來實現檔案的下載(而不是瀏覽器開啟或瀏覽),對於動態內容,就無能為力。

例如,我們對頁面進行分享的時候,希望分享圖片是頁面內容的實時截圖,此時,這個圖片就是動態的,純HTML顯然是無法滿足我們的需求的,藉助JS和其它一些HTML5特性,例如,將頁面元素轉換到canvas上,然後再轉成圖片進行下載,可參見“SVG <foreignObject>簡介與截圖等應用”一文。

但本文要介紹的下載不是圖片的下載,而是文字資訊的下載,所需要使用的HTML特性不是canvas,而是其它。

二、藉助HTML5 Blob實現文字資訊檔案下載

如果對Blob不瞭解,可以先看看我好些年之前寫的“理解DOMString、Document、FormData、Blob、File、ArrayBuffer資料型別”一文。

原理其實很簡單,我們可以將文字或者JS字串資訊藉助Blob轉換成二進位制,然後,作為<a>元素的href屬性,配合download屬性,實現下載。

程式碼也比較簡單,如下示意(相容Chrome和Firefox):

var funDownload = function (content, filename) {
    // 建立隱藏的可下載連結
    var eleLink = document.createElement('a');
    eleLink.download = filename;
    eleLink.style.display = 'none';
    // 字元內容轉變成blob地址
    var blob = new Blob([content]);
    eleLink.href = URL.createObjectURL(blob);
    // 觸發點選
    document.body.appendChild(eleLink);
    eleLink.click();
    // 然後移除
    document.body.removeChild(eleLink);
};複製程式碼

其中,content指需要下載的文字或字串內容,filename指下載到系統中的檔名稱。

萬般言語不達意,一枚例項來走心。

您可以狠狠地點選這裡:基於funDownload實現的html格式檔案下載demo

點選“下載”按鈕,會把文字域中的內容全部作為一個.html字尾檔案下載下來,各流程效果如下面幾張圖:

下載按鈕點選示意

出現下載確認框(根據瀏覽器的設定不同也可能直接下載),然後名稱預設就是test.html

預設就是test.html名稱

然後對應儲存目錄就多了個類似下圖的檔案:

儲存好的test.html檔案截圖示意

雙擊該test.html檔案可以在瀏覽器中正常瀏覽,說明,儲存資訊無誤。

test.html在瀏覽器中訪問的效果

觸發下載的JS程式碼就幾行:

button.addEventListener('click', function () {
    funDownload(textarea.value, 'test.html');	
});複製程式碼

三、藉助Base64實現任意檔案下載

對於非文字檔案,也是可以直接JS觸發下載的,例如,如果我們想下載一張圖片,可以把這張圖片轉換成base64格式,然後下載。

程式碼示意:

var funDownload = function (domImg, filename) {
    // 建立隱藏的可下載連結
    var eleLink = document.createElement('a');
    eleLink.download = filename;
    eleLink.style.display = 'none';
    // 圖片轉base64地址
    var canvas = document.createElement('canvas');
    var context = canvas.getContext('2d');
    var width = domImg.naturalWidth;
    var height = domImg.naturalHeight;    context.drawImage(domImg, 0, 0);
    // 如果是PNG圖片,則canvas.toDataURL('image/png')
    eleLink.href = canvas.toDataURL('image/jpeg');
    // 觸發點選
    document.body.appendChild(eleLink);
    eleLink.click();
    // 然後移除
    document.body.removeChild(eleLink);
};複製程式碼

四、結束語

不止是.html檔案,.txt, .json等文字檔案都可以使用這種小技巧實現下載。

在Chrome瀏覽器下,模擬點選建立的<a>元素即使不append到頁面中,也是可以觸發下載的,但是在Firefox瀏覽器中卻不行,因此,上面的funDownload()方法有一個appendChildremoveChild的處理,就是為了相容Firefox瀏覽器。

download屬性從Edge13開始支援,根據同行測試可以觸發下載,不過生成的檔案命名類似GUID,需要手動再加個字尾。

就這些,感謝閱讀!

純JS生成並下載各種文字檔案或圖片


相關文章