HttpResponse.Filter 屬性,類似於 HttpRequest.Filter,只不過一個是出口,一個是入口(想像一下停車場),在這兩個點之間的資料由伺服器端處理,在這兩點之外的,則由使用者瀏覽器處理。那麼,在出口處能做些什麼呢?當然是對資料進行一些統一的處理,比如說簡繁轉換、過濾非法詞彙等等。
在這裡說說如何做簡繁轉換,其實網上已經有很多例子,所以只是針對一些重點的部分說明一下:
首先,依然是實現自己的過濾器,需要繼承 Stream:
public class ResponseFilter : Stream
在重寫基類方法時,最重要的是 Write() 方法,所有的轉換都在該方法中實現,主要代碼如下:
- public override void Write(byte[] buffer, int offset, int count)
- {
- //判斷 Session,若 Session["Lang"] 等於 "ZH-TW",則啟動轉換
- if (HttpContext.Current.Session != null && HttpContext.Current.Session["Lang"].ToString() == "ZH-TW")
- {
- //對於 UTF-8 編碼,必須提供簡繁字對照,為提高處理效率,應刪除簡繁體寫法相同的字,這樣至少可以減少 2/3 的字數(網上提供的字型檔大多包含了相同字元的)
- //GB 轉 Big5 可使用 Microsoft.VisualBasic.Strings.StrConv 方法,不需要字型檔。
- String simple = "簡體字型檔";
- String tradit = "繁體字庫";
-
- //擷取當前響應流的編碼方式,即使整個網站都使用 UTF-8 編碼,但仍然會存在其它的編碼方式,尤其是採用微軟的 Ajax 控制項時,若編碼方式不一致,則會導致錯誤,動態擷取編碼,可避免這個問題
- System.Text.Encoding curEncoding = HttpContext.Current.Response.ContentEncoding;
- string strBuff = curEncoding.GetString(buffer);
- int len = strBuff.Length;
- System.Text.StringBuilder sbBuff = new System.Text.StringBuilder();
- for (int i = 0; i != len; ++i)
- {
- int index = simple.IndexOf(strBuff[i]);
- if (index != -1)
- sbBuff.Append(tradit[index]);
- else
- sbBuff.Append(strBuff[i]);
- }
- byte[] output = System.Text.Encoding.UTF8.GetBytes(sbBuff.ToString());
- m_sink.Write(output, 0, count);
- }
- else
- m_sink.Write(buffer, 0, count);
- }
寫好自己的過濾器後,就可以載入到網站中了,注意,跟 HttpRequest.Filter 一樣,HttpResponse.Filter 的載入也是在 Global.asax 的 Application_BeginRequest 事件中,另外,因為在該事件觸發時,Session 尚未啟動,所以不能在此使用Session 判定當前的語言,代碼如下:
- void Application_BeginRequest(object sender, EventArgs e)
- {
- string rawUrl = Request.RawUrl.ToLower();
- // rawUrl.IndexOf(".axd")用於屏蔽 Asp.net Ajax 產生的非同步請求。否則部分使用 Ajax 的頁面會報錯,原因不明。
- if (rawUrl.IndexOf(".axd") == -1)
- {
- this.Response.Charset = "UTF-8";
- this.Response.Buffer = false;
- this.Response.Filter = new ResponseFilter(Response.Filter);
- }
- }
至此,一個簡單的網站簡繁轉換就完成了,但在實際應用中,出現過這樣一種情況,有時在訪問網站時,會提示
工作階段狀態已經建立工作階段 ID,但由於應用程式已經清除回應而無法儲存。
出現的頻率不高,並且無規律,即使當前未進行轉換也會出現,並且只出現在頁面下方,也不像通常的錯誤顯示一樣,僅出現錯誤資訊,而是錯誤資訊和本來的頁面都顯示出來。
後來在一份文檔中看到說是使用 Response.Flush、Response.Write 等導致輸出緩衝區重新整理的語句,有時會造成 Session 丟失(因為網站另外使用了一些 Session 來儲存一些狀態值),所以在 Global.asax 的建立 Session 事件中,重建網站需要的狀態 Session 值:
- void Session_Start(object sender, EventArgs e)
- {
- //判斷 Session 是否丟失
- if (!String.IsNullOrEmpty(Session.SessionID))
- {
- //網站狀態 Session 設為預設值(這裡不用管用於判斷是簡體還是繁體那個 Session)
- … …
- }
- }
問題解決。
有可能還會有這種需求,要將一些帶有簡體字的圖片也轉換為繁體,怎麼辦呢?呵呵,其實很簡單,對需要轉換的圖片名稱後加一個特殊的字串,比如簡體的 圖片名為 "image__zh__.gif“,相應的繁體圖片為 "image__tw__.gif",將 __zh__ 替換為 __tw__就可以了。