Asp.NET匯出Excel檔案亂碼解決若干方法
在Asp.NET開發過程中經常會將一些清單項目匯出為Excel方便使用者查看和儲存,但是也經常遇到檔案名稱亂碼、檔案內容亂碼等問題。最近我也接到了這樣的Bug,現總結了若干個解決辦法,供遇到問題的朋友們參考一下。希望以下的某些方法可以解決您的問題。
程式邏輯及問題
前端點擊匯出Excel之後,從後台資料庫中綁定資料到GridView控制項,將GridView控制項的內容儲存到臨時檔案。最後從臨時檔案讀取資料流並輸出到前台。
問題:有些列表匯出到Excel之後開啟顯示亂碼。檔案名稱在IE6下顯示亂碼,在IE8下顯示正常。
關注點
除了考慮程式方面的問題之外首先還需要先考慮以下幾個方面:
作業系統
這裡包括伺服器與用戶端的作業系統,如果是在中文的環境下建議直接安裝中文的作業系統。對於英語或者其它語言的作業系統需要在地區和語言選項裡安裝東亞字元集,將語言和時區都選擇中國。這可以解決英文作業系統下無法顯示中文字元的問題。
資料庫
跟作業系統一樣最好直接安裝中文版的資料庫,另外對於中文字元的欄位類型應該選擇運行中文的欄位類型。往資料庫插入中文字元的時候記得在字串前面加"N”,如
insert into MyTable(name,nickname) values('Gary Zhang',N'地球人');
“有些資料內容顯示亂碼”是因為在不同資料庫下產生的現像,但沒有深入去檢查資料庫的問題,所以就暫時不討論。
瀏覽器的支援
不同的瀏覽器對於檔案名稱的編碼也是不一樣的,因此在編碼時需要注意不同瀏覽器的支援,或者是否是因為瀏覽器問題引起亂碼。比如常見的瀏覽器對含有中文字元的檔案名稱顯示亂碼。目前這個檔案名稱在IE6亂碼的問題還沒有解決,即經過UTF-8編碼的中文檔案名稱在IE6下直接開啟檔案名稱還會顯示亂碼,而儲存而不會有這個問題。在IE8下則都不會有問題。
參考《如何在下載檔案名稱中使用UTF-8編碼》中提到的關於不同瀏覽器對於Content-Description的支援,可以自己試一下。
IE6 |
attachment; filename="<URL編碼之後的UTF-8檔案名稱>" |
FF3 |
attachment; filename="UTF-8檔案名稱" |
attachment; filename*="utf8''<URL編碼之後的UTF-8檔案名稱>" |
O9 |
attachment; filename="UTF-8檔案名稱" |
Safari3(Win) |
貌似不支援?上述方法都不行 |
使用統一的編碼方式
Excel資料檔案匯出的整個過程可能前期的資料錄入資料庫->取資料填充GridView等控制項或者產生相應的Table表格->轉換成stream並輸出等過程。在整個過程中盡量使用統一的常用的編碼方式比如UTF-8,以名在字元的轉換過程中導致字元亂碼。
開發方法
查看了以上的關注點都沒有問題之後,檢查程式的輸出代碼也沒有發現問題,程式部分代碼如下:
HttpResponse response = Page.Response;
response.Clear();
response.ContentType = "application/octet-stream";
//使用UTF-8對檔案名稱進行編碼
response.AppendHeader("Content-Disposition", "attachment;filename=\"" + HttpUtility.UrlEncode(disFileName, System.Text.Encoding.UTF8) + "\"");
response.ContentType = "application/ms-excel;";
試著對response對像也設定了charset等屬性(其實本來我已經使用了utf-8編碼了在轉換成stream的時候)。不出所料結果還是不行。
response.Charset = "UTF-8";
response.ContentEncoding = System.Text.Encoding.UTF8;
response.HeaderEncoding = System.Text.Encoding.UTF8;
終極解決方案
幾乎尋找了所有的Excel亂碼的解決方案。都試了一遍都沒有辦法。突然在切換網頁的時候發現Google的頁面可以查看而我用IE開啟的更改了尾碼名的Excel檔案卻是不可以看的。突然想到在網頁中可以使用<meta>去聲明瀏覽器應該使用哪一種編碼去顯示頁面。因此也想到了可以在匯出資料的時候加上一段聲明。
因為實際上使用DataGride控制項匯出的資料實際上就是一個table.跟HTML標籤是一樣的。因此Excel既然可以識別HTML的Table標籤那麼也應該可以識別HTML聲明。這樣Excel就知道該用什麼字元集去解析內容了。產生的輸出內容如下所示:
<meta http-equiv="content-type" content="application/ms-excel; charset=UTF-8"/>
<table>
<tr>
<td>cbcye@live.com | http://www.cbcye.com </td> …
</tr>
<table>