前端 js 匯出csv檔案(使用a標籤)
前言
匯出檔案,使用最多的方式還是伺服器端來處理。比如jsp 中使用response 的方式。
但是,有時候可能就想使用web 前端是否也可以把頁面上的內容匯出來呢? 比如說,匯出頁面的一個表格。
這個需求肯定是有答案的,只是對於各瀏覽器處理會稍微不一樣。(主要是IE 和其他瀏覽器的區別)。
在IE中使用ActiveXObject 實現,在firefox 和Chrome 中使用 a 標籤(或者js)就可以實現了。 這裡主要講一下其他瀏覽器中的實現。
使用 a 標籤實現方式
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="author" content="oscar999">
<title></title>
</head>
<body>
<a id="test" download="downlaod.txt" href="data:text/txt;charset=utf-8,download Test Data" >download</a>
</body>
</html>
說明一下:
1. download 設定下載的檔名。
2. href 加上 data:text/txt;charset=utf-8 分別設定點選link 是下載檔案,編碼是utf-8,這個逗號後面的就是儲存在檔案中的內容了。
以多行,多列匯出csv 檔案
csv 檔案可以用Excel開啟, 如果是匯出一個table 的話,使用Excel 就方便很多了。
問題是: 如何分行, 分列?
理論上 : 分列使用 , 號分割, 分行用 \n .
可以用以上方式,會發現列可以分開,但是不換行。 看上去不認識 \n.
解決方式是使用 encodeURIComponent 進行編碼
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="author" content="oscar999">
<title>
</title>
<script>
function clickDownload(aLink)
{
var str = "col1,col2,col3\nvalue1,value2,value3";
str = encodeURIComponent(str);
aLink.href = "data:text/csv;charset=utf-8,"+str;
aLink.click();
}
</script>
</head>
<body>
<a id="test" onclick="clickDownload(this)" download="downlaod.csv" href="#">download</a>
</body>
</html>
帶中文問題的csv 匯出
以上使用的都是utf-8 編碼,理論上匯出中文應該不是問題。
但是匯出csv 格式的話, 使用Excel 開啟會發現中文是亂碼,但是用其他文字程式開啟確是正常的。
原因就是少了一個 BOM頭 。 \ufeff。
加上一切都正常了,
<head>
<meta http-equiv="content-type" content="text/html; charset=gb2312">
<meta name="author" content="oscar999">
<title>
</title>
<script>
function clickDownload(aLink)
{
var str = "欄位1,欄位2,欄位3\n值1,值2,值3";
str = encodeURIComponent(str);
aLink.href = "data:text/csv;charset=utf-8,\ufeff"+str;
aLink.click();
}
</script>
</head>
<body>
<a id="test" onclick="clickDownload(this)" download="downlaod.csv" href="#">download</a>
</body>
</html>
這裡有兩個改變
1. 頁面的charset 需設定成gb2312。
2. 加上 \ufeff BOM 頭。
Chrome下載的檔名
以上使用 a 的download 屬性可以指定下載的檔名及字尾。 但是在Chrome 執行的時候會發現, Chrome 壓根不理會這個。
下載名是 “下載” 或是 “download”.
上網搜尋一下, 有說是Chrome 的 bug.
參見 stackoverflow 中的兩篇文章:
http://stackoverflow.com/questions/23962284/download-attribute-on-a-tag-doesnt-work-in-chrome
http://stackoverflow.com/questions/23816005/anchor-tag-download-attribute-not-working-bug-in-chrome-35-0-1916-114
以上兩篇文章可以不去關注, 需要關注的是這個問題是否可以解決, 以及解決的方法是什麼?
直接貼解決方案:
var blob = new Blob([data], { type: 'text/csv' }); //new way
var csvUrl = URL.createObjectURL(blob);
document.getElementById("mylink").href = csvUrl;
使用Blob 和URL 來封裝和轉換. 問題解決。
這裡如遇中文問題, 和上面的處理方式是一樣的:
1. 頁面的charset 需設定成gb2312 (設成UTF-8 也可以)。
2. 加上 \ufeff BOM 頭具體的程式碼類似:
data = "\ufeff"+data;
var blob = new Blob([data], { type: 'text/csv,charset=UTF-8'});