• 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编码

  • 相关阅读:
    UVALive 7509 Dome and Steles
    HDU 5884 Sort
    Gym 101194H Great Cells
    HDU 5451 Best Solver
    HDU 5883 The Best Path
    HDU 5875 Function
    卡特兰数
    UVa 11729 Commando War 突击战
    UVa 11292 The Dragon of Loowater 勇者斗恶龙
    Spark Scala Flink版本对应关系
  • 原文地址:https://www.cnblogs.com/freshman0216/p/4172655.html
Copyright © 2020-2023  润新知