備注學院

          LuLu

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            5 隨筆 :: 50 文章 :: 16 評論 :: 0 Trackbacks

          [版權聲明]:版權歸作者所有,轉載時請以超鏈接形式標明文章原始出處和作者信息及本聲明:
          http://www.open-lib.com/Forum/Read_69_1.action

          前言:

          當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中有這樣的一段代碼:

          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方法的代碼片段,下面是正常調用jquery ajax post的代碼:

          $.ajax({
           url: ajaxurl,
           type: 'POST',
           dataType: 'html',
           timeout: 
          20000,//超時時間設定
           data:para,//參數設置
           success: function(html){

           }
          });

          通過上面代碼可以知道,當設置了data時候,jquery內部會調用jQuery.param方法對參數encode(執行本應瀏覽器處理的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的代碼,細心點可以留意到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代碼:

          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的源文件重寫,可以在你項目的javascript貼上,覆蓋它原有的方法,不過必須在jquery加載之后。

          經初步驗證,上面那段代碼在utf-8編碼也可以工作正常,大概是編碼成unicode的緣故吧。

          這樣,就不是需要使用什么二次編碼,即影響前臺,又影響后臺。gbk編碼下ajax post不再是問題了,此乃是終極解決方法。哈哈。

          有興趣的可以到http://www.open-lib.com/Forum/Read_69_1.action與作者交流。

          posted on 2010-10-18 20:08 smildlzj 閱讀(1828) 評論(3)  編輯  收藏

          評論

          # re: jQuery ajax在GBK編碼下表單提交終極解決方案(非二次編碼方法) 2010-10-18 22:04 heqs
          不錯的方法。。。  回復  更多評論
            

          # re: jQuery ajax在GBK編碼下表單提交終極解決方案(非二次編碼方法) 2010-10-20 22:52 Unmi
          好辦法,改核心代碼會有些麻煩,可否寫個 jQuery 的插件來改變默認的行為。

          關于 ajax,都是使用 utf8 字符集的,像 dwr, prototype 都是這樣子的。

          不過,我所參與的項目都是使用 utf-8 的字符集,可以避免這樣的錯誤。  回復  更多評論
            

          # re: jQuery ajax在GBK編碼下表單提交終極解決方案(非二次編碼方法) 2010-10-20 23:09 smildlzj
          @Unmi
          utf-8編碼下當然不存在問題.
          只是有的項目不是utf-8,例如163就不是了..

          這個雖然是改變核心代碼,但是只是在外部覆蓋原有方法..

          至于你說寫成插件,其實也不是啥問題....等于是單獨一套ajax,拋棄原有jq的..  回復  更多評論
            


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 乡宁县| 卫辉市| 齐齐哈尔市| 临城县| 铁岭市| 监利县| 香港| 紫阳县| 和龙市| 云浮市| 吉隆县| 西安市| 沙坪坝区| 炉霍县| 澄城县| 平安县| 会理县| 溆浦县| 大宁县| 岐山县| 丽水市| 兴海县| 武夷山市| 七台河市| 凤山市| 田林县| 荃湾区| 信阳市| 玛纳斯县| 格尔木市| 灯塔市| 进贤县| 贵港市| 乐山市| 华阴市| 福泉市| 巴塘县| 商河县| 仁寿县| 惠来县| 淮阳县|