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

  • 相关阅读:
    深入理解Node.js垃圾回收与内存管理
    【File System】Node.js中文件操作模块File System
    【事件流】事件冒泡和事件捕获
    undefined 和null的区别?
    localStorage实现登录注册功能
    解刨for循环
    react中嵌入高德地图并Marker标点
    react页面中嵌入地图,标识出某个地点,使用插件react-amap
    react中使用antd的List组件,以及下载文件,List隔行变色
    公众号页面数据处理
  • 原文地址:https://www.cnblogs.com/freshman0216/p/4172655.html
Copyright © 2020-2023  润新知