某天發現問題來了, 以前都能下載的報表, 突然發現異常.
1. 直接下載後開啟, 會發現ZIP檔裡都是空的
2. 若是儲存後再用檔案總管開啟, 發現檔案變亂碼且有部份檔案不見
3. 再用7-ZIP去開啟壓縮檔, 會看到所有檔案, 但是所有檔名都變成亂碼
研究了很久, 還換了一個壓ZIP的元件(原本是用ShapZipLib, 後來改用DotNetZip)
因為來源的報表檔案的編碼是UTF-8, 所以我在壓ZIP檔時, 一直都覺得應該ZIP檔也是要壓成UTF-8或是Unicode, 這樣的放到各種OS的主機上, 看到的字才會正確顯示; 結果當然是什麼鬼也沒看到 =.=q
中間的甘苦就不提了, 直接說結論:
a. ZIP檔的編碼必須指定為使用者OS的語系
b. ZIP檔內的檔案名文字也必須轉換為使用者OS的語系
P.S 假設有一個Archive.zip的zip檔, 裡面壓了一個"每日結算報表.TXT"
這個TXT本身的編碼可能是UTF-8或是其它任何編碼,
但是不會影響上面下的結論
以下是ASP.NET使用DotNetZip輸出二種語系(簡體 & 繁體)ZIP檔的程式碼.
//使用前先下載DotNetZip, 並且引用其中的Ionic.Zip.dll
Response.Clear();
string zipFilename = DateTime.Now.ToString("yyyMMddHHmmss") + ".zip";Response.ContentType = "application/zip";
Response.AddHeader("content-disposition", "filename=" + zipFilename);
Encoding sysLocate = Encoding.GetEncoding(936); //預設ZIP檔的檔案編碼為簡體中文
//判斷Client的語系
if (Request.Headers["Accept-Language"].ToUpper() == "ZH-TW"){
sysLocate= Encoding.GetEncoding(950); //繁體中文
}
using (ZipFile zip = new ZipFile(sysLocate))
{ //files變數是輸出檔案清單的完整路徑
foreach (string file in files){
ZipEntry entry = zip.AddFile(file, "");
if (Request.Headers["Accept-Language"].ToUpper() == "ZH-TW")
{entry.FileName = ToTraditional(entry.FileName); //把簡體檔名換成繁體檔名
}
logger.Info(entry.FileName);
}zip.Save(Response.OutputStream);
}
Response.End();
4. 以下圖片是二種不同語系OS去下載報表, 得到的不同結果.
使用DotNetZip, 在壓縮時設定ZIP檔的編碼, 且轉換所有檔案的檔名
使用DotNetZip, 在壓縮時設定ZIP檔的編碼, 且轉換所有檔案的檔名
B. 簡體主機的使用者
沒有留言:
張貼留言