js實現txt/excel檔案下載

weixin_33763244發表於2018-06-13
出於安全考慮,JS無法直接呼叫FileAPI寫檔案到磁碟,但是卻可以通過下載來變相實現儲存功能。
JS要實現下載功能,一般都是這麼幾個過程:生成下載的URL,動態建立一個A標籤,並將其href指向生成的URL,然後觸發A標籤的單擊事件,這樣就會彈出下載對話方塊,從而實現了一個下載的功能。

HTML5的download屬性

這個屬性很重要,它可以指定下載檔名,並且可以告訴瀏覽器目標連結是一個下載連結,不是一個普通連結,我們看下面程式碼就能看出區別了:

<a href="data:text/txt;charset=utf-8,測試下載純文字" rel="external nofollow" rel="external nofollow" rel="external nofollow" download="測試.txt" >下載1</a>
<a href="data:text/txt;charset=utf-8,測試下載純文字" rel="external nofollow" rel="external nofollow" rel="external nofollow" >下載2</a>

可以發現,下載1按鈕能夠實現下載,點選下載2連結時直接在瀏覽器開啟檔案內容了。

JS生成CSV檔案並下載

csv是一種逗號分隔的表格檔案格式,可以很好的被Excel支援,由於其檔案格式簡單,所以經常用在簡單的表格上面。最重要的是它是一種純文字格式,可以很輕鬆地用JS來生成而不借助第三方庫。

不考慮相容性的儲存CSV方法:

/**
 * 儲存CSV檔案
 * @params csv csv檔案內容
 * @params saveName 儲存的檔名
 */
function saveCSV(csv, saveName){
 var a = document.createElement('a');
 a.href = 'data:text/csv;charset=utf-8,\ufeff' + encodeURIComponent(csv);
 a.download = saveName;
 a.click();
}
雖然我們用的是UTF-8編碼,下載後你會發現,用文字編輯器開啟沒問題,但是用Excel開啟亂碼:
原因就是少了一個ufeffBOM頭,所以在data裡面新增一個\ufeff解決了

文字換行問題

文字換csv的最大問題就是如何處理換行,很簡單,使用`\n`,`\r`後再用encodeURIComponent編碼一下就可以了。

大部分瀏覽器可能都沒啥問題,但是一些比較老的Chrome可能下載的時候指定的download就是不生效,此時可以用blob來解決:(測試此方法測試在微軟Edge瀏覽器和IE11下都無法下載)

考慮相容性的儲存CSV方法:

/**
 * 儲存CSV檔案
 * @params csv csv檔案內容
 * @params saveName 儲存的檔名
 */
function saveCSV(csv, saveName)
{
 var blob = new Blob(['\ufeff' + csv], {type: 'text/csv,charset=UTF-8'});
 openDownloadDialog(blob, saveName);
}

此方法測試在微軟Edge瀏覽器可以實現下載,但是在IE11下還是無法下載

封裝下載函式

const openDownloadDialog = (url, saveName) => {
  if (typeof url === 'object' && url instanceof Blob) {
    url = URL.createObjectURL(url); // 建立blob地址
  }
  const aLink = document.createElement('a');
  aLink.href = url;
  aLink.download = saveName;
  aLink.click();
};

txt檔案

下載text檔案只需要修改一下檔案型別就行了

function saveTXT(csv, saveName)
{
 var blob = new Blob(['\ufeff' + csv], {type: 'text/txt,charset=UTF-8'});
 openDownloadDialog(blob, saveName);
}

注意事項

儲存檔案的檔名字尾會影響開啟方式,如果是.csv的檔名,預設開啟為excel,.txt檔案結尾的預設開啟方式為text檔案。所以這點需要注意

參考程式碼

我自己在專案中的封裝

downLoadTools.js


const openDownloadDialog = (url, saveName) => {
  if (typeof url === 'object' && url instanceof Blob) {
    url = URL.createObjectURL(url); // 建立blob地址
  }
  const aLink = document.createElement('a');
  aLink.href = url;
  aLink.download = saveName;
  aLink.click();
};
export default {
  /**
   * 儲存CSV檔案
   * @params csv csv檔案內容
   * @params saveName 儲存的檔名
   */
  saveCSV: (csv, saveName) => {
    const blob = new Blob(['\ufeff' + csv], {type: 'text/csv,charset=UTF-8'});
    openDownloadDialog(blob, `${saveName}.csv`);
  },
  saveTXT: (csv, saveName) => {
    // const href = 'data:text/txt;charset=utf-8,\ufeff' + encodeURIComponent(csv); // ie瀏覽器不支援
    const blob = new Blob(['\ufeff' + csv], {type: 'text/tet,charset=UTF-8'});
    openDownloadDialog(blob, `${saveName}.txt`);
  }
};

頁面引用

import downLoadTools from '@/utils/downLoadTools';  // 引入

downLoadTools.saveTXT(csv, '檔名');               // csv是一個字串, 最終會下載一個 檔名.txt 的檔案

相關文章