起因:
今天早上被同僚問了一個問題:說接收到的參數是亂碼,讓我幫着解決一下。
實際情景:
同僚負責的平台是ext.js架構搭建的,web.config配置檔案裡配置了全局為“gb2312”編碼:
<globalization requestencoding="gb2312" responseencoding="gb2312" fileencoding="gb2312" culture="zh-cn"/>
目前台送出“中文文字”時,背景用request.querystring["xxx"]接收到的是亂碼。
無論用system.web.httputility.urldecode("xxx","編碼類型")怎麼解碼都無效。
原理說明:
1:首先确定的是:用戶端的url參數在送出時,ext.js會對其編碼再送出,而用戶端的編碼預設是utf-8編碼
用戶端預設有三種編碼函數:escape() encodeuri() encodeuricomponent()
2:那為什麼用request.querystring["xxx"]接收參數時,收到的會是亂碼?
為此,我們必須解開request.querystring的原始處理邏輯過程
我們步步反編繹,
2.1:看querystring屬性的代碼:
public namevaluecollection querystring
{
get
{
if (this._querystring == null)
{
this._querystring = new httpvaluecollection();
if (this._wr != null)
{
this.fillinquerystringcollection();//重點代碼切入點
}
this._querystring.makereadonly();
}
if (this._flags[1])
this._flags.clear(1);
validatenamevaluecollection(this._querystring, "request.querystring");
return this._querystring;
}
}
private void fillinquerystringcollection()
byte[] querystringbytes = this.querystringbytes;
if (querystringbytes != null)
if (querystringbytes.length != 0)
this._querystring.fillfromencodedbytes(querystringbytes, this.querystringencoding);
}//上面是對流位元組的處理,即檔案上傳之類的。
else if (!string.isnullorempty(this.querystringtext))
//下面這句是對普通檔案送出的處理:fillfromstring是個切入點,編碼切入點是:this.querystringencoding
this._querystring.fillfromstring(this.querystringtext, true, this.querystringencoding);
internal encoding querystringencoding
encoding contentencoding = this.contentencoding;
if (!contentencoding.equals(encoding.unicode))
return contentencoding;
return encoding.utf8;
//點選進入this.contentencoding則為:
public encoding contentencoding
if (!this._flags[0x20] || (this._encoding == null))
this._encoding = this.getencodingfromheaders();
if (this._encoding == null)
globalizationsection globalization = runtimeconfig.getlkgconfig(this._context).globalization;
this._encoding = globalization.requestencoding;
this._flags.set(0x20);
return this._encoding;
set
this._encoding = value;
this._flags.set(0x20);
說明:
從querystringencoding代碼得出,系統預設會先取globalization配置節點的編碼方式,如果取不到,則預設為utf-8編碼方式
代碼有點長,就折疊起來了
從這點我們發現:所有的參數輸入,都調用了一次:httputility.urldecode(str2, encoding);
3:結論出來了
當用戶端js對中文以utf-8編碼送出到服務端時,用request.querystring接收時,會先以globalization配置的gb2312去解碼一次,于是,産生了亂碼。
所有的起因為:
1:js編碼方式為urt-8
2:服務端又配置了預設為gb2312
3:request.querystring預設又會調用httputility.urldecode用系統配置編碼去解碼接收參數。
文章補充:
1:系統取預設編碼的順序為:http請求頭->globalization配置節點-》預設utf-8
2:在url直接輸入中文時,不同浏覽器處理方式可能不同如:ie不進行編碼直接送出,firefox對url進行gb2312編碼後送出。
3:對于未編碼“中文字元”,使用request.querystring時内部調用httputility.urldecode後,由gb2312->utf-8時,
如果查不到該中文字元,預設轉成"%ufffd",是以出現不可逆亂碼。
4:解決之路
知道了原理,解決的方式也有多種多樣了:
1:全局統一為utf-8編碼,省事又省心。
2:全局指定了gb2312編碼時,url帶中文,js非編碼不可,如ext.js架構。
這種方式你隻能特殊處理,在服務端指定編碼解碼,
因為預設系統調用了一次httputility.urldecode("xxx",系統配置的編碼),
是以你再調用一次httputility.urlencode("xxx",系統配置的編碼),傳回到原始urt-8編碼參數
再用httputility.urldecode("xxx",utf-8),解碼即可。
5:其它說明:預設對進行一次解碼的還包括uri屬性,而request.rawurl則為原始參數
版權聲明:本文原創發表于部落格園,作者為路過秋天,原文連結:
http://www.cnblogs.com/cyq1162/archive/2010/11/29/1891124.html