jquery ajax在GBK編碼下亂碼解決方法

 
前言:
當jquery ajax在utf-8編碼下(頁面utf-8,接收utf-8),無任何問題。可以正常post、get,處理頁面直接獲取正確的內容。
但在以下情況下:
GBK -> AJAX POST ->GBK
UTF-8 -> AJAX POST ->GBK
後臺代碼無法獲取正確的內容,通常表現爲獲取到奇怪字符、問號。
經典解決方法:
1:發送頁面、接收頁面均採用UTF-8編碼。
2:發送頁面在調用ajax post方法之前,將含有中文內容的input用encodeURIComponent編碼一次,而接收頁面則調用解碼方法( 如:java.net.urldecoder.decode("接收到內容","utf-8")  )。

其中,第一種方法無疑是最簡單、最直接,但往往不符合實際,因爲很多項目並不是使用utf-8編碼,例如國內大部分使用gbk編碼,也不可能爲了解決這樣一個問題,而將整個項目轉換爲utf-8編碼,成本太大,風險太高。
第二方法,是現在最多人使用的方法,俗稱二次編碼,爲什麼叫二次編碼,等下會解釋。客戶端編碼兩次,服務端解碼兩次。但這種方法不好的地方,就是前臺手動編碼一次,後臺再手動解碼一次,稍不留神就會忘記,而且代碼摻和前臺邏輯。
交互過程:
當我們使用表單按照傳統方式post提交時候(非AJAX提交),瀏覽器會根據當前頁面編碼,encode一次,然後發送到服務端,服務端接收到表單,會自動dencode一次,通常這個過程是對程序是透明的,因此加上手動編碼、解碼,就變成上面所說的二次編碼。
但當我們使用AJAX方式提交時候,瀏覽器並不會自動替我們encode,因此在jquery中有這樣的一段代碼:
Js代碼 複製代碼 收藏代碼
  1. ajax: function( s ) {   
  2.     // Extend the settings, but re-extend 's' so that it can be   
  3.     // checked again later (in the test suite, specifically)   
  4.     s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));   
  5.   
  6.     var jsonp, jsre = /=?(&|$)/g, status, data,   
  7.         type = s.type.toUpperCase();   
  8.   
  9.     // convert data if not already a string   
  10.     if ( s.data && s.processData && typeof s.data !== "string" )   
  11.         s.data = jQuery.param(s.data);   
  12. ........       
  13. }  
 
以上是jquery的ajax方法的代碼片段,下面是正常調用jquery ajax post的代碼:
Js代碼 複製代碼 收藏代碼
  1. $.ajax({   
  2.  url: ajaxurl,   
  3.  type: 'POST',   
  4.  dataType: 'html',   
  5.  timeout: 20000,//超時時間設定   
  6.  data:para,//參數設置   
  7.  success: function(html){   
  8.   
  9.  }   
  10. });  
 
通過上面代碼可以知道,當設置了data時候,jquery內部會調用jQuery.param方法對參數encode(執行本應瀏覽器處理的encode)。
Js代碼 複製代碼 收藏代碼
  1. jQuery.param=function( a ) {   
  2.     var s = [ ];   
  3.     function add( key, value ){   
  4.         s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value);   
  5.     };   
  6.     // If an array was passed in, assume that it is an array   
  7.     // of form elements   
  8.     if ( jQuery.isArray(a) || a.jquery )   
  9.         // Serialize the form elements   
  10.         jQuery.each( a, function(){   
  11.             add( this.name, this.value );   
  12.         });   
  13.   
  14.     // Otherwise, assume that it's an object of key/value pairs   
  15.     else  
  16.         // Serialize the key/values   
  17.         for ( var j in a )   
  18.             // If the value is an array then the key names need to be repeated   
  19.             if ( jQuery.isArray(a[j]) )   
  20.                 jQuery.each( a[j], function(){   
  21.                     add( j, this );   
  22.                 });   
  23.             else  
  24.                 add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );   
  25.   
  26.     // Return the resulting serialization   
  27.     return s.join("&").replace(/%20/g, "+");   
  28. }//jquery.param end  
 
上面是jQuery.param的代碼,細心點可以留意到encodeURIComponent這方法,這是javascript內置的方法,對目標字符串執行utf-8 encode,因此,當頁面使用gbk編碼時候,服務端會使用gbk進行解碼,但實際提交的數據是以utf-8編碼的,所以造成接收到內容爲亂碼或者爲問號。
解決方法:
encodeURIComponent會以utf-8編碼,在gbk編碼下,可不可以以gbk進行編碼呢?
如果還在打encodeURIComponent主意的話,那不好意思,encodeURIComponent只會utf-8編碼,並沒有其他api進行其他編碼;不過,別擔心,看看下面:
encodeURIComponent,它是將中文、韓文等特殊字符轉換成utf-8格式的url編碼。
escape對0-255以外的unicode值進行編碼時輸出%u****格式,其它情況下escape,encodeURI,encodeURIComponent編碼結果相同。
哈哈,看到希望吧?沒錯,就是用escape代替encodeURIComponent方法,不過必須注意:
escape不編碼字符有69個:*,+,-,.,/,@,_,0-9,a-z,A-Z
encodeURIComponent不編碼字符有71個:!, ',(,),*,-,.,_,~,0-9,a-z,A-Z
使用了escape之後必須對加號進行編碼,否則,當內容含有加號時候會被服務端翻譯爲空格。
終於知道解決辦法了,重寫jquery代碼:
Js代碼 複製代碼 收藏代碼
  1. jQuery.param=function( a ) {   
  2.     var s = [ ];   
  3.     var encode=function(str){   
  4.         str=escape(str);   
  5.         str=str.replace(/+/g,"%u002B");   
  6.         return str;   
  7.     };   
  8.     function add( key, value ){   
  9.         s[ s.length ] = encode(key) + '=' + encode(value);   
  10.     };   
  11.     // If an array was passed in, assume that it is an array   
  12.     // of form elements   
  13.     if ( jQuery.isArray(a) || a.jquery )   
  14.         // Serialize the form elements   
  15.         jQuery.each( a, function(){   
  16.             add( this.name, this.value );   
  17.         });   
  18.   
  19.     // Otherwise, assume that it's an object of key/value pairs   
  20.     else  
  21.         // Serialize the key/values   
  22.         for ( var j in a )   
  23.             // If the value is an array then the key names need to be repeated   
  24.             if ( jQuery.isArray(a[j]) )   
  25.                 jQuery.each( a[j], function(){   
  26.                     add( j, this );   
  27.                 });   
  28.             else  
  29.                 add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );   
  30.   
  31.     // Return the resulting serialization   
  32.     return s.join("&").replace(/%20/g, "+");   
  33. }  
 
 
上面那段代碼並不需要在jquery的源文件重寫,可以在你項目的javascript貼上,覆蓋它原有的方法,不過必須在jquery加載之後。
經初步驗證,上面那段代碼在utf-8編碼也可以工作正常,大概是編碼成unicode的緣故吧。
這樣,就不是需要使用什麼二次編碼,即影響前臺,又影響後臺。gbk編碼下ajax post不再是問題了,此乃是終極解決方法。哈哈。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章