1. 程式人生 > >$.ajax在谷歌瀏覽器傳入中文亂碼的情況

$.ajax在谷歌瀏覽器傳入中文亂碼的情況

有運營同學反映,後臺編輯的一箇中文顯示名稱,前臺亂碼了,於是乎~~

先看程式碼是否get請求沒轉碼:

[javascript] view plain copy
  1. $.ajax({  
  2.     type: 'POST',  
  3.     url: '/admin/updatedisplayname}',  
  4.     data: {displayName:displayName},  
  5.     success: function(res){  
  6.         alert(1);  
  7.     },  
  8.     error: function() {  
  9.         alert(2);  
  10.     },  
  11.     dataType: 'json'
  12. })  

這段程式碼不管怎麼看,也沒有問題,post請求過去的,應該不會存在亂碼問題,自己測了下,修改回去了,沒亂碼(火狐)

奇怪~

問了下,對方用的是谷歌,檢查他的瀏覽器編碼有沒特殊設定過,沒有,一切正常。

納悶,回來在谷歌測試下,暈死,果然重現,亂碼了,哈哈,那就好辦,查~

看看請求頭資訊啥的,發現使用$.ajax請求的時候有一個值有問題

chrome:contentType: 'application/x-www-form-urlencoded'

ff:contentType: 'application/x-www-form-urlencoded; charset=UTF-8',

難道是這個在作祟,如果乎~

[javascript] view plain copy
  1. $.ajax({  
  2.     type: 'POST',  
  3.     url: '/admin/updatedisplayname}',  
  4.     data: {displayName:displayName},  
  5.     contentType: 'application/x-www-form-urlencoded; charset=UTF-8',  
  6.     success: function(res){  
  7.         alert(1);  
  8.     },  
  9.     error: function
    () {  
  10.         alert(2);  
  11.     },  
  12.     dataType: 'json'
  13. })  
加上引數測試,果然在谷歌下不亂碼了,問題解決。

莫不是有啥玄機,檢視jQuery手冊

contentTypeString

(預設: "application/x-www-form-urlencoded") 傳送資訊至伺服器時內容編碼型別。預設值適合大多數情況。如果你明確地傳遞了一個content-type給 $.ajax() 那麼他必定會發送給伺服器(即使沒有資料要傳送)


為毛我在不傳入這個值的時候,火狐會加上 charset=UTF-8呢?

看看jquery原始碼:

[javascript] view plain copy
  1. ajaxSettings: {  
  2.         url: location.href,  
  3.         global: true,  
  4.         type: "GET",  
  5.         contentType: "application/x-www-form-urlencoded",  
  6.         processData: true,  
  7.         async: true,  
  8.         /* 
  9.         timeout: 0, 
  10.         data: null, 
  11.         username: null, 
  12.         password: null, 
  13.         traditional: false, 
  14.         */
  15.         // Create the request object; Microsoft failed to properly
  16.         // implement the XMLHttpRequest in IE7 (can't request local files),
  17.         // so we use the ActiveXObject when it is available
  18.         // This function can be overriden by calling jQuery.ajaxSetup
  19.         xhr: window.XMLHttpRequest && (window.location.protocol !== "file:" || !window.ActiveXObject) ?  
  20.             function() {  
  21.                 returnnew window.XMLHttpRequest();  
  22.             } :  
  23.             function() {  
  24.                 try {  
  25.                     returnnew window.ActiveXObject("Microsoft.XMLHTTP");  
  26.                 } catch(e) {}  
  27.             },  
  28.         accepts: {  
  29.             xml: "application/xml, text/xml",  
  30.             html: "text/html",  
  31.             script: "text/javascript, application/javascript",  
  32.             json: "application/json, text/javascript",  
  33.             text: "text/plain",  
  34.             _default: "*/*"
  35.         }  
  36.     },  
貌似問題已經找到,通知團隊成員,仔細檢查所有專案的$.ajax方法的使用,是否有傳遞中文引數,如果有就加上: [javascript] view plain copy
  1. contentType: 'application/x-www-form-urlencoded; charset=UTF-8',  

果然發現了幾個隱藏的bug,不過像這樣的直接使用$.ajax一般只有後臺系統才用用到,而我們的後臺系統是可以不相容google的,所以當時測試的時候可能沒測到。

不過,又有問題,有同學沒有加,但是測試是ok的,谷歌不亂碼,各種不淡定啊。。。。

再查~

首先想到檢查jquery版本,果然,這哥們是用jquery1.7.2,而我用的是1.4.2,檢視1.7.2的原始碼:

[javascript] view plain copy
  1. ajaxSettings: {  
  2.         url: ajaxLocation,  
  3.         isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),  
  4.         global: true,  
  5.         type: "GET",  
  6.         contentType: "application/x-www-form-urlencoded; charset=UTF-8",  
  7.         processData: true,  
  8.         async: true,  
  9.         /* 
  10.         timeout: 0, 
  11.         data: null, 
  12.         dataType: null, 
  13.         username: null, 
  14.         password: null, 
  15.         cache: null, 
  16.         traditional: false, 
  17.         headers: {}, 
  18.         */
  19.         accepts: {  
  20.             xml: "application/xml, text/xml",  
  21.             html: "text/html",  
  22.             text: "text/plain",  
  23.             json: "application/json, text/javascript",  
  24.             "*": allTypes  
  25.         },  
  26.         contents: {  
  27.             xml: /xml/,  
  28.             html: /html/,  
  29.             json: /json/  
  30.         },  
  31.         responseFields: {  
  32.             xml: "responseXML",  
  33.             text: "responseText"
  34.         },  
  35.         // List of data converters
  36.         // 1) key format is "source_type destination_type" (a single space in-between)
  37.         // 2) the catchall symbol "*" can be used for source_type
  38.         converters: {  
  39.             // Convert anything to text
  40.             "* text": window.String,  
  41.             // Text to html (true = no transformation)
  42.             "text html"true,  
  43.             // Evaluate text as a json expression
  44.             "text json": jQuery.parseJSON,  
  45.             // Parse text as xml
  46.             "text xml": jQuery.parseXML  
  47.         },  
  48.         // For options that shouldn't be deep extended:
  49.         // you can add your own custom options here if
  50.         // and when you create one that shouldn't be
  51.         // deep extended (see ajaxExtend)
  52.         flatOptions: {  
  53.             context: true,  
  54.             url: true
  55.         }  
  56.     },  

暈死,在1.7.2中居然加上了charset=UTF-8,

各種~~~~,再探~1.7原始碼裡面也是沒有的

好吧,1.7.2裡面沒有這個問題。

結論:

1、使用1.7.2之前的版本,在使用$.ajax的時候需要自行設定contentType否則,谷歌會亂碼。

2、跟瀏覽器也有關係,火狐就可以自動加上utf-8而谷歌則不會,也行jquery團隊發現這個問題,所以就在最新版更正了這個問題。

測試及生成環境:

1、Java環境,打包gbk,頁面編碼gbk,tomcat中URIEncoding配置utf-8等,也許應該跟這些伺服器配置也是有關係的,就不深究下去了。

猜測:一般post表單請求的請求資料編碼是按照頁面裡面的meta指定的編碼格式編碼的,我們頁面是gbk的,所以在谷歌瀏覽器在未指定ajax的contentType引數的時候採用預設頁面編碼方式gbk編碼然後傳送到伺服器端,而我們tomcat裡面的URIEncoding是utf-8的,所以就兩邊編碼不一樣,就亂碼了,顯式的指定一下就ok。不過貌似ajax統一都是utf-8的來編碼的,就算不指定也不會有問題,莫不是谷歌。。。。