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

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

       1. 瀏覽器解碼html

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

  <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。jquery

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

 

       2. 提交表單時的編碼web

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

<%@ 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編碼 app

        在瀏覽器中輸入地址: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編碼

相關文章
相關標籤/搜索