Request 接收參數亂碼原理解析二:瀏覽器端編碼原理


       上一篇《Request 接收參數亂碼原理解析一:服務器端解碼原理》,分析了服務器端解碼的過程,那么瀏覽器是根據什么編碼的呢?

       1. 瀏覽器解碼

       瀏覽器根據服務器頁面響應Header中的“Content-Type: text/html; charset=gb2312”解碼。修改web.config中“responseEncoding=utf-8”,發現服務器頁面響應Header變成了“Content-Type: text/html; charset=utf8”。

  <system.web>
    <globalization requestEncoding="gb2312" responseEncoding="gb2312"/>
  </system.web>

       除了web.config中的globalization結點可以影響charset,修改頁面Page_Load(配置文件仍為gb2312),發現頁面charset輸出也變成了utf-8,但同時也發現頁面中的中文成了亂碼。微軟對Response.Charset的解釋是獲取或設置輸出流的HTTP字符集,為什么會出現亂碼?個人猜測可能整個頁面是按照web.config中指定GB2312編碼的,但輸出的時候將字符集強制變成了utf-8。

        protected void Page_Load(object sender, EventArgs e)
        {
            Response.Charset = "utf-8";
        }

 

       2. 提交表單時的編碼

       頁面Get或者Post提交form表單數據時,會對表單中的中文進行編碼,而編碼方式是由服務器頁面響應Header中的“Content-Type: text/html; charset=gb2312”確定的(和瀏覽器解碼方式一致)。示例代碼:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="EncodeTest.aspx.cs" Inherits="Com.Shizi.Time8.UI.Test.WebTest.EncodeTest" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>頁面編碼測試</title>
    <script type="text/javascript" src="Scripts/jquery-2.1.1.min.js"></script>
</head>
<body>
    <form id="form1" action="EncodeTest.aspx" method="post">
        <div>
            <input type="text" name="name" id="name" value="北京" />
        </div>
        <div>
            <input type="submit" name="btnSumbit" value="sumbmit" /></div>
    </form>
    <div>
        <input type="button" name="btnAjaxPost" value="AJaxPost提交" onclick="AjaxPost()" />
        <input type="button" name="btnAjaxGet" value="AJaxGet提交" onclick="AjaxGet()" /></div>
    <div id="divMessage" style="color:red"></div>
    <script type="text/javascript">
        function AjaxGet() {
            $.ajax({
                type: "GET",
                url: "EncodeTest.aspx?namequery=" + $("#name").val(),
                data: { name: $("#name").val(), action: "ajax", methodtype: "get" },
                success: function (data) {
                    $("#divMessage").html(data);
                }
            });
        }
        function AjaxPost() {
            $.ajax({
                type: "POST",
                url: "EncodeTest.aspx?namequery=" + $("#name").val(),
                data: { name: $("#name").val(), action: "ajax", methodtype: "post" },
                success: function (data) {
                    $("#divMessage").text(data);
                }
            });
        }

    </script>
</body>
</html>
EncodeTest.aspx代碼

       不管get提交還是post提交,input控件全部都進行了GB2312編碼,提交的數據為“name=%B1%B1%BE%A9&btnSumbit=sumbmit”。修改web.config中“responseEncoding=utf-8”,發現服務器頁面響應Header中的“Content-Type: text/html; charset=utf8”,再次提交表單時編碼已經成了utf-8,內容變為“name=%E5%8C%97%E4%BA%AC&btnSumbit=sumbmit”。

       觀察發現,不管get提交還是post提交,HTTP請求中並沒有指定服務器端的解碼方式,服務器端解碼還是根據服務器配置獲取的,本例中是用GB2312解碼的。

       

        3. 瀏覽器地址欄Url編碼 

        在瀏覽器中輸入地址:http://localhost:52443/EncodeTest.aspx?name=北京,“name=北京”的編碼方式隨瀏覽器不同而不同,IE11編碼方式為GBK,服務器用GB2312解碼正確;Firefox34.0編碼方式為utf-8,服務器GB2312解碼亂碼。URL中的編碼依賴於瀏覽器,開發中不建議使用,一些地址鏈接含有中文時,建議在生成鏈接時,對中文指定編碼方式編碼。

 

        4. JQuery中的AJax提交 

        JQuery是一款優秀的js框架,被廣泛使用,但通過AJax提交數據時,卻容易出現亂碼。通過測試和分析JQuery源碼,AJax請求時,推薦方式為:

        1)POST請求:參數放到data中,無需對參數值編碼,JQuery在構造HTTP請求時,會調用js的函數encodeURIComponent()對data中的鍵值對分別進行utf-8編碼,服務器用utf-8解碼。url中對應的就是url地址,不能含有參數。

        即使服務器Globalization結點配置的GB2312解碼,Request.Form["xxx"]也會用utf-8解碼,因為AJax的post請求中在HTTP頭添加了代碼“Content-Type: text/html; charset=utf8”,告訴服務器用utf-8解碼,達到編碼和解碼一致的目的。這點可能和我們平時想的不一樣,整站配置為GB2312編碼的站點,竟然AJax的post請求都是用的utf-8編碼!

        // 拼裝參數
        if ( s.data && s.processData && typeof s.data !== "string" ) {
            s.data = jQuery.param( s.data, s.traditional );
        }
        

        // 如果有post data的話,設置請求Header
        if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
            jqXHR.setRequestHeader( "Content-Type", s.contentType );
        }


// key/values into a query string
jQuery.param = function( a, traditional ) {
    var prefix,
        s = [],
        add = function( key, value ) {
            // If value is a function, invoke it and return its value
            value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
            s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
        };

    // Set traditional to true for jQuery <= 1.3.2 behavior.
    if ( traditional === undefined ) {
        traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
    }

    // If an array was passed in, assume that it is an array of form elements.
    if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
        // Serialize the form elements
        jQuery.each( a, function() {
            add( this.name, this.value );
        });

    } else {
        // If traditional, encode the "old" way (the way 1.3.2 or older
        // did it), otherwise encode params recursively.
        for ( prefix in a ) {
            buildParams( prefix, a[ prefix ], traditional, add );
        }
    }

    // Return the resulting serialization
    return s.join( "&" ).replace( r20, "+" );
};    
JQuery AJax核心代碼

        2)GET請求:參數放在Url中,並按照和服務器一致的編碼方式編碼,如服務器配置的Globalization結點為UTF-8,則將參數值用UTF-8編碼,可以調用函數encodeURIComponent();如果服務器配置為GB2312,則將參數用GB2312編碼,可以調用escape()。Get和Post請求的一大差別是,GET請求不會改變請求的Header,Request.QueyString["xxx"]解碼用的是Globalization指定的編碼。

         如下面的代碼,在配置為GB2312編碼的站點運行正常,無亂碼,其中post請求是utf-8解碼,get請求是gb2312解碼。

        function AjaxGet() {
            $.ajax({
                type: "GET",
                url: "EncodeTest.aspx?namequery=" + escape($("#name").val()),
                success: function (data) {
                    $("#divMessage").html(data);
                }
            });
        }
        function AjaxPost() {
            $.ajax({
                type: "POST",
                url: "EncodeTest.aspx",
                data: { name: $("#name").val(), action: "ajax", methodtype: "post" },
                success: function (data) {
                    $("#divMessage").text(data);
                }
            });
        }

        默認情況下,JQuery的AJax方法通過post提交數據,編碼都是用的utf-8,通過Header指定服務器解碼方式也為utf-8,但某些特殊情況下可能想服務器用gb2312解碼(現在想來應該不需要這種場景,因為本身就不大合理,當時可能在某些不大合理的前提下確實需要來着,還不停的百度),網上查找資料是說AJax時,添加屬性“contentType: "application/x-www-form-urlencoded; charset=utf-8",”個人測試IE下生效了,服務器變成了GB2312解碼,但火狐下未生效,原因未知,單步跟蹤了代碼都執行了,沒啥問題。

        參考:Asp.net中Response.Charset 與Response.ContentEncoding區別charset 和character encoding深入淺出URL編碼


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM