2012年7月4日 星期三

UrlPathEncode 用於檔案下載出現亂碼的問題

近日在閱讀 郝冠軍 所著的「ASP.NET本質論」,裡面提到了有關 UrlEncode 與 UrlPathEncode 的差別。我對於裡面有關 UrlPathEncode 的定義比較有興趣,因為他寫著:

UrlEncode 首先使用回應中的編碼對內容進行編碼,編碼後的字節數組再看成是ASCII 字符,
其中A~Z、a~z、0~9、-、_、.、!、*、\、 (、) 被認為是安全的字符,不需要特殊編碼。
其他字符需要經過字符編碼,空格被編碼為+,剩下的被編碼為% 引導的十六進製表示方法。

UrlPathEncode 僅僅編碼Url 的Path 部分
UrlPathEncode 首先使用UTF8 編碼對字符串進行轉換,將轉換後的結果看成ASCII 串,然後,
將其中的空格替換為%20。

但自己實際上去實作一下發現下面結果:

一、輸入字串來源是 URL :http://paladinprogram.blogspot.tw/index.aspx?q=心 亞.jpg
UrlEncode →http%3a%2f%2fpaladinprogram.blogspot.tw%2findex.aspx%3fq%3d%e5%bf%83+%e4%ba%9e.jpg
UrlPathEncode →http://paladinprogram.blogspot.tw/index.aspx?q=心 亞.jpg

二、輸入字串來源非 URL :心 亞.jpg
UrlEncode →%e5%bf%83+%e4%ba%9e.jpg
UrlPathEncode →%e5%bf%83%20%e4%ba%9e.jpg

UrlPathEncode 如果是針對 URL 字串,則只會對 Path 的部份進行處理,但如果非字串的話,則全部都會被編碼。在編碼的時候,遇到空白字元的處理上,UrlEncode 是把他用 + 來取代,而 UrlPathEncode 則是用 %20 來取代。

接著,該書的作者,透過 UrlPathEncode 對空白編碼處理的特性,把他應用在處理檔案下載時,檔案名稱是亂碼的問題。可以參考:编码与解码。這方法在 IE 、 Chrome 上可以完美解決,但是在 FireFox 上卻還是不行。於是再翻出自己以前所整理過的一篇文章「檔案下載或開啟時出現亂碼檔名」,看看現在會不會激發出新的解法,蠻慶幸地,又有另一種解法可以選擇了。

這次處理亂碼檔名的過程中,有了 2 個方向去處理:
1.各家瀏覽器,如果下載檔名直接給他中文,除了 IE 之外,其餘都可以正常。所以使用區別瀏覽器的作法。
2.對於下載檔名,如果名字中間有空白,FireFox 會發生截斷的現象,但是透過引號將檔名包起來,則可以正常[ ref:檔案下載solution]。

於是新的寫法如下:

protected void btnDownload_Click(object sender, EventArgs e)
{
    string str = "江 苏.doc";
    if (Context.Request.Browser.Browser == "IE")
        str = Context.Server.UrlPathEncode(str);
    else
        str = string.Format("\"{0}\"", str);
          
    Context.Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}", str));
            
}


與先前舊寫法最大的不同,就是屏棄了

Response.HeaderEncoding = System.Text.Encoding.GetEncoding("big5");

的寫法,打破了僅支援繁體中文的限制了。

測試程式:下載

參考:
01:ASP.NET本質論
02:编码与解码
03:檔案下載或開啟時出現亂碼檔名
04:檔案下載solution

沒有留言:

張貼留言