[版權(quán)聲明]:版權(quán)歸作者所有,轉(zhuǎn)載時(shí)請(qǐng)以超鏈接形式標(biāo)明文章原始出處和作者信息及本聲明:
http://www.open-lib.com/Forum/Read_69_1.action
前言:
當(dāng)jquery ajax在utf-8編碼下(頁(yè)面utf-8,接收utf-8),無(wú)任何問(wèn)題。可以正常post、get,處理頁(yè)面直接獲取正確的內(nèi)容。
但在以下情況下:
GBK -> AJAX POST ->GBK
UTF-8 -> AJAX POST ->GBK
后臺(tái)代碼無(wú)法獲取正確的內(nèi)容,通常表現(xiàn)為獲取到奇怪字符、問(wèn)號(hào)。
經(jīng)典解決方法:
1:發(fā)送頁(yè)面、接收頁(yè)面均采用UTF-8編碼。
2:發(fā)送頁(yè)面在調(diào)用ajax post方法之前,將含有中文內(nèi)容的input用encodeURIComponent編碼一次,而接收頁(yè)面則調(diào)用解碼方法( 如:java.net.urldecoder.decode("接收到內(nèi)容","utf-8") )。
其中,第一種方法無(wú)疑是最簡(jiǎn)單、最直接,但往往不符合實(shí)際,因?yàn)楹芏囗?xiàng)目并不是使用utf-8編碼,例如國(guó)內(nèi)大部分使用gbk編碼,也不可能為了解決這樣一個(gè)問(wèn)題,而將整個(gè)項(xiàng)目轉(zhuǎn)換為utf-8編碼,成本太大,風(fēng)險(xiǎn)太高。
第二方法,是現(xiàn)在最多人使用的方法,俗稱(chēng)二次編碼,為什么叫二次編碼,等下會(huì)解釋。客戶(hù)端編碼兩次,服務(wù)端解碼兩次。但這種方法不好的地方,就是前臺(tái)手動(dòng)編碼一次,后臺(tái)再手動(dòng)解碼一次,稍不留神就會(huì)忘記,而且代碼摻和前臺(tái)邏輯。
交互過(guò)程:
當(dāng)我們使用表單按照傳統(tǒng)方式post提交時(shí)候(非AJAX提交),瀏覽器會(huì)根據(jù)當(dāng)前頁(yè)面編碼,encode一次,然后發(fā)送到服務(wù)端,服務(wù)端接收到表單,會(huì)自動(dòng)dencode一次,通常這個(gè)過(guò)程是對(duì)程序是透明的,因此加上手動(dòng)編碼、解碼,就變成上面所說(shuō)的二次編碼。
但當(dāng)我們使用AJAX方式提交時(shí)候,瀏覽器并不會(huì)自動(dòng)替我們encode,因此在jquery中有這樣的一段代碼:
ajax: function( s ) {
// Extend the settings, but re-extend 's' so that it can be
// checked again later (in the test suite, specifically)
s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
var jsonp, jsre = /=?(&|$)/g, status, data,
type = s.type.toUpperCase();
// convert data if not already a string
if ( s.data && s.processData && typeof s.data !== "string" )
s.data = jQuery.param(s.data);

..
}
以上是jquery的ajax方法的代碼片段,下面是正常調(diào)用jquery ajax post的代碼:
$.ajax({
url: ajaxurl,
type: 'POST',
dataType: 'html',
timeout: 20000,//超時(shí)時(shí)間設(shè)定
data:para,//參數(shù)設(shè)置
success: function(html){
}
});
通過(guò)上面代碼可以知道,當(dāng)設(shè)置了data時(shí)候,jquery內(nèi)部會(huì)調(diào)用jQuery.param方法對(duì)參數(shù)encode(執(zhí)行本應(yīng)瀏覽器處理的encode)。
jQuery.param=function( a ) {
var s = [ ];
function add( key, value ){
s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value);
};
// If an array was passed in, assume that it is an array
// of form elements
if ( jQuery.isArray(a) || a.jquery )
// Serialize the form elements
jQuery.each( a, function(){
add( this.name, this.value );
});
// Otherwise, assume that it's an object of key/value pairs
else
// Serialize the key/values
for ( var j in a )
// If the value is an array then the key names need to be repeated
if ( jQuery.isArray(a[j]) )
jQuery.each( a[j], function(){
add( j, this );
});
else
add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );
// Return the resulting serialization
return s.join("&").replace(/%20/g, "+");
}//jquery.param end
上面是jQuery.param的代碼,細(xì)心點(diǎn)可以留意到encodeURIComponent這方法,這是javascript內(nèi)置的方法,對(duì)目標(biāo)字符串執(zhí)行utf-8 encode,因此,當(dāng)頁(yè)面使用gbk編碼時(shí)候,服務(wù)端會(huì)使用gbk進(jìn)行解碼,但實(shí)際提交的數(shù)據(jù)是以u(píng)tf-8編碼的,所以造成接收到內(nèi)容為亂碼或者為問(wèn)號(hào)。
解決方法:
encodeURIComponent會(huì)以u(píng)tf-8編碼,在gbk編碼下,可不可以以gbk進(jìn)行編碼呢?
如果還在打encodeURIComponent主意的話(huà),那不好意思,encodeURIComponent只會(huì)utf-8編碼,并沒(méi)有其他api進(jìn)行其他編碼;不過(guò),別擔(dān)心,看看下面:
encodeURIComponent,它是將中文、韓文等特殊字符轉(zhuǎn)換成utf-8格式的url編碼。
escape對(duì)0-255以外的unicode值進(jìn)行編碼時(shí)輸出%u****格式,其它情況下escape,encodeURI,encodeURIComponent編碼結(jié)果相同。
哈哈,看到希望吧?沒(méi)錯(cuò),就是用escape代替encodeURIComponent方法,不過(guò)必須注意:
escape不編碼字符有69個(gè):*,+,-,.,/,@,_,0-9,a-z,A-Z
encodeURIComponent不編碼字符有71個(gè):!, ',(,),*,-,.,_,~,0-9,a-z,A-Z
使用了escape之后必須對(duì)加號(hào)進(jìn)行編碼,否則,當(dāng)內(nèi)容含有加號(hào)時(shí)候會(huì)被服務(wù)端翻譯為空格。
終于知道解決辦法了,重寫(xiě)jquery代碼:
jQuery.param=function( a ) {
var s = [ ];
var encode=function(str){
str=escape(str);
str=str.replace(/+/g,"%u002B");
return str;
};
function add( key, value ){
s[ s.length ] = encode(key) + '=' + encode(value);
};
// If an array was passed in, assume that it is an array
// of form elements
if ( jQuery.isArray(a) || a.jquery )
// Serialize the form elements
jQuery.each( a, function(){
add( this.name, this.value );
});
// Otherwise, assume that it's an object of key/value pairs
else
// Serialize the key/values
for ( var j in a )
// If the value is an array then the key names need to be repeated
if ( jQuery.isArray(a[j]) )
jQuery.each( a[j], function(){
add( j, this );
});
else
add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );
// Return the resulting serialization
return s.join("&").replace(/%20/g, "+");
}
上面那段代碼并不需要在jquery的源文件重寫(xiě),可以在你項(xiàng)目的javascript貼上,覆蓋它原有的方法,不過(guò)必須在jquery加載之后。
經(jīng)初步驗(yàn)證,上面那段代碼在utf-8編碼也可以工作正常,大概是編碼成unicode的緣故吧。
這樣,就不是需要使用什么二次編碼,即影響前臺(tái),又影響后臺(tái)。gbk編碼下ajax post不再是問(wèn)題了,此乃是終極解決方法。哈哈。
有興趣的可以到http://www.open-lib.com/Forum/Read_69_1.action與作者交流。