JS 下載/導出 csv、excel、txt 、img等文件的方法總結

1. 調用後端接口導出文件

示例下載接口url https://gold-cdn.xitu.io/extension/0.3.9/package.crxjavascript

1.1 window.open(url)

會打開一個新窗口,開始下載後會自動關閉新窗口。Safair 下載後沒有關閉新窗口。
Chrome、IE、Safair支持,貌似火狐不支持html

1.2 window.location=url

在當前窗口下載前端

Chrome、Safair支持java

1.3 iframe

function downloadByIframe (url) {
    try {
        const iframe = document.createElement('iframe');
        iframe.src = url;
        iframe.style.display = 'none';
        document.body.appendChild(iframe);
    } catch (e) {
        
    }
}
複製代碼
<button onclick="downloadByIframe(url)">下載</button>
複製代碼

在HTML中,iframe 的屬性用src,但在JS中,只有部份瀏覽器支持修改src(讀是沒問題),真正通用的是要修改對應框架的href值。chrome

function changeIframeSrc (url) {
    window.iframes['myIframe'].location.href = url;
}
複製代碼

1.4 <a href="url" download="filename">點擊連接下載</a>

function downloadByAElement (url, fileName) {
    try {
        const element = document.createElement('a');
        element.href = url;
        element.download = fileName;
        const a = document.body.appendChild(element);
        a.click();
        document.body.removeChild(element);
    } catch (e) {
        
    }
}
downloadByAElement ('https://gold-cdn.xitu.io/extension/0.3.9/package.crx', 'test');
複製代碼

HTML5中給a標籤增長了一個download屬性,只要有這個屬性,點擊這個連接時瀏覽器就不在打開連接指向的文件,而是改成下載,目前只有chrome、firefox、opera、Edge支持。經常使用此方法點擊下載圖片。
IE既不支持a標籤的download屬性也不容許js調用a 標籤的click方法。json

2. 前端直接導出文件到本地

2.1 將數據轉成DataURI用<a>標籤下載

<a href="DataURI" download="filename">點擊連接下載</a>segmentfault

function saveData2File (data, fileName) {
    try {
        const element = document.createElement('a');
        cosnt uri = getDownloadUri(data);
        element.href = uri;
        element.download = fileName;
        const a = document.body.appendChild(element);
        cosnt evt = document.createEvent('HTMLEvents');
        evt.initEvent('click', false, false); // 不加後面兩個參數在Firefox上報錯
        a.dispatchEvent(evt);
        document.body.removeChild(element);
    } catch (e) {
        
    }
}
複製代碼

注意: 瀏覽器對href屬性的URL長度有限制,若超過瀏覽器自身限制的最大長度會致使下載失敗。windows

瀏覽器 最大長度(字符數) 備註
IE 2083 若是超過這個數字,提交按鈕沒有任何反應
Firefox 65,536 -
Chrome 8,182 -
Safari 80,000 -
Opera 190,000

Data URI Scheme

Data URI Scheme是指能夠在Web 頁面中包含圖片但無需任何額外的HTTP 請求的一類URI。 Data URI Scheme通常用於將通過base64編碼的數據嵌入網頁中,從而減小請求資源的連接數。IE8 以前的版本都不支持 data URI scheme後端

DataURI的格式:

data: [<mime-type>][;charset=<charset>][;<encoding>],<encoded data>
複製代碼
  • data: 協議名稱
  • [<mime-type>] 可選項,數據類型,經常使用的有 image/png, image/svg+xml, text/plain
  • [;charset=<charset>] 可選項,源文本的字符集編碼方式。[<mime type>][;charset=<charset>] 的缺省值爲HTTP Header 中Content-Type的字段值;
  • [;<encoding>] 數據編碼方式(有US-ASCII,BASE64 兩種),默認值爲US-ASCII,就是每一個字符會編碼爲%xx的形式
  • ,<encoded data> 編碼後的數據, 若是 <encoded data> 不是以 [;<encoding>] 方式編碼的數據,則會報異常

生成DataURI的方式

1. encodeURIComponent
function getDownloadUri (data) {
    const mimeType = 'attachment/csv';
    const charset = ';charset=utf-8,';
    const _utf = '\uFEFF'; // 爲了使文件以utf-8的編碼模式,同時也是解決中文亂碼的問題
    return 'data:' + mimeType + charset + _utf + encodeURIComponent(data)
}
複製代碼

使用這種方式,當數據過多時,URI長度容易超出瀏覽器限制。 encodeURIComponent經常使用來轉碼接口參數,爲了不服務器收到不可預知的請求,對任何用戶輸入的做爲URI部分的內容都須要用encodeURIComponent進行轉義。設計模式

2. URL.createObjectURL

URL.createObjectURL的參數是File對象或者Blob對象

  • File對象也就是經過input[type=file]選擇的文件
  • Blob對象表示一個不可變、原始數據的類文件對象

IE10如下不支持URL.createObjectURL

function getDownloadUri (data) {
    const _utf = '\uFEFF'; // 爲了使文件以utf-8的編碼模式,同時也是解決中文亂碼的問題
    if (window.Blob && window.URL && window.URL.createObjectURL) {
        const blob = new Blob([_utf + data], {
            type: 'text/json' // 寫本身須要的數據格式
        });
        return URL.createObjectURL(blob);
    }
}
複製代碼

2.2 windows.navigator.msSaveBlob IE10~Edge 專用

msSaveBlob 是IE10~Edge 私有方法。

function downloadByMsSaveBlob (data) {
    const _utf = '\uFEFF'; // 爲了使文件以utf-8的編碼模式,同時也是解決中文亂碼的問題
    const blob = new Blob([_utf + data], {
        type: 'text/json' // 本身須要的數據格式
    });
    navigator.msSaveBlob(_csvData, fileName); 
}
複製代碼

2.3 execCommand

當一個HTML文檔切換到設計模式時,document暴露 execCommand 方法,該方法容許運行命令來操縱可編輯內容區域的元素。

有的資料有提到IE9可使用execCommand方法來保存數據到本地文件,可是我本身沒有驗證過,不知道是否可行。並且MDN文檔中execCommand沒有查到SaveAs命令。這塊只是作個小記錄。

function saveFileByExecCommand (data, fileName) {
    const newWindow = window.top.open('about:blank', '_blank');
    newWindow.document.write('sep=,\r\n' + data);
    newWindow.document.close();
    newWindow.document.execCommand('SaveAs', false, fileName);
    newWindow.close();
}
複製代碼

js數據直接導出/下載數據到本地到方法總結

function saveData2File (data, fileName) {
    const bw = getBrowser(); // 獲取瀏覽器信息
    if (!bw['edge'] || !bw['ie']) {
        const element = document.createElement('a');
        cosnt uri = getDownloadUri(data);
        element.href = uri;
        element.download = fileName;
        const a = document.body.appendChild(element);
        cosnt evt = document.createEvent('HTMLEvents');
        evt.initEvent('click', false, false); // 不加後面兩個參數在Firefox上報錯
        a.dispatchEvent(evt);
        document.body.removeChild(element);
    } else if (bw['ie'] >= 10 || bw['edge'] === 'edge') {
      const _utf = '\uFEFF'; // 爲了使文件以utf-8的編碼模式,同時也是解決中文亂碼的問題
      const blob = new Blob([_utf + data], {
        type: 'text/json' // 本身須要的數據格式
      });
      navigator.msSaveBlob(blob, fileName);
    }
}

function getBrowser () {
    const sys = {};
    const ua = navigator.userAgent.toLowerCase();
    if (ua.indexOf('edge') !== -1) {
      sys.edge = 'edge';
    } else if (ua.match(/rv:([\d.]+)\) like gecko/)) {
      sys.ie = ua.match(/rv:([\d.]+)\) like gecko/)[1];
    } else if (ua.match(/msie ([\d.]+)/)) {
      sys.ie = ua.match(/msie ([\d.]+)/)[1];
    } else if (ua.match(/firefox\/([\d.]+)/)) {
      sys.firefox = ua.match(/firefox\/([\d.]+)/)[1];
    } else if (ua.match(/chrome\/([\d.]+)/)) {
      sys.chrome = ua.match(/chrome\/([\d.]+)/)[1];
    } else if (ua.match(/opera.([\d.]+)/)) {
      sys.opera = ua.match(/opera.([\d.]+)/)[1];
    } else if (ua.match(/version\/([\d.]+).*safari/)) {
      sys.safari = ua.match(/version\/([\d.]+).*safari/)[1];
    }
    return sys;
  }

複製代碼

參考資料:

相關文章
相關標籤/搜索