天天看點

Request 接收參數亂碼原了解析

起因:

今天早上被同僚問了一個問題:說接收到的參數是亂碼,讓我幫着解決一下。

實際情景:

Request 接收參數亂碼原了解析
Request 接收參數亂碼原了解析

同僚負責的平台是ext.js架構搭建的,web.config配置檔案裡配置了全局為“gb2312”編碼:

<globalization requestencoding="gb2312" responseencoding="gb2312" fileencoding="gb2312" culture="zh-cn"/>

目前台送出“中文文字”時,背景用request.querystring["xxx"]接收到的是亂碼。

無論用system.web.httputility.urldecode("xxx","編碼類型")怎麼解碼都無效。

Request 接收參數亂碼原了解析

原理說明:

1:首先确定的是:用戶端的url參數在送出時,ext.js會對其編碼再送出,而用戶端的編碼預設是utf-8編碼

用戶端預設有三種編碼函數:escape() encodeuri() encodeuricomponent()

2:那為什麼用request.querystring["xxx"]接收參數時,收到的會是亂碼?

為此,我們必須解開request.querystring的原始處理邏輯過程

我們步步反編繹,

2.1:看querystring屬性的代碼:

Request 接收參數亂碼原了解析
Request 接收參數亂碼原了解析

public namevaluecollection querystring

{

    get

    {

        if (this._querystring == null)

        {

            this._querystring = new httpvaluecollection();

            if (this._wr != null)

            {

                this.fillinquerystringcollection();//重點代碼切入點

            }

            this._querystring.makereadonly();

        }

        if (this._flags[1])

            this._flags.clear(1);

            validatenamevaluecollection(this._querystring, "request.querystring");

        return this._querystring;

    }

}

Request 接收參數亂碼原了解析
Request 接收參數亂碼原了解析
Request 接收參數亂碼原了解析

private void fillinquerystringcollection()

    byte[] querystringbytes = this.querystringbytes;

    if (querystringbytes != null)

        if (querystringbytes.length != 0)

            this._querystring.fillfromencodedbytes(querystringbytes, this.querystringencoding);

    }//上面是對流位元組的處理,即檔案上傳之類的。

    else if (!string.isnullorempty(this.querystringtext))

        //下面這句是對普通檔案送出的處理:fillfromstring是個切入點,編碼切入點是:this.querystringencoding

        this._querystring.fillfromstring(this.querystringtext, true, this.querystringencoding);

Request 接收參數亂碼原了解析
Request 接收參數亂碼原了解析
Request 接收參數亂碼原了解析

internal encoding querystringencoding

        encoding contentencoding = this.contentencoding;

        if (!contentencoding.equals(encoding.unicode))

            return contentencoding;

        return encoding.utf8;

//點選進入this.contentencoding則為:

public encoding contentencoding

        if (!this._flags[0x20] || (this._encoding == null))

            this._encoding = this.getencodingfromheaders();

            if (this._encoding == null)

                globalizationsection globalization = runtimeconfig.getlkgconfig(this._context).globalization;

                this._encoding = globalization.requestencoding;

            this._flags.set(0x20);

        return this._encoding;

    set

        this._encoding = value;

        this._flags.set(0x20);

Request 接收參數亂碼原了解析

說明:

從querystringencoding代碼得出,系統預設會先取globalization配置節點的編碼方式,如果取不到,則預設為utf-8編碼方式

Request 接收參數亂碼原了解析

代碼有點長,就折疊起來了

從這點我們發現:所有的參數輸入,都調用了一次:httputility.urldecode(str2, encoding);

3:結論出來了

當用戶端js對中文以utf-8編碼送出到服務端時,用request.querystring接收時,會先以globalization配置的gb2312去解碼一次,于是,産生了亂碼。

所有的起因為:

1:js編碼方式為urt-8

2:服務端又配置了預設為gb2312

3:request.querystring預設又會調用httputility.urldecode用系統配置編碼去解碼接收參數。

文章補充:

Request 接收參數亂碼原了解析
Request 接收參數亂碼原了解析

1:系統取預設編碼的順序為:http請求頭->globalization配置節點-》預設utf-8

2:在url直接輸入中文時,不同浏覽器處理方式可能不同如:ie不進行編碼直接送出,firefox對url進行gb2312編碼後送出。

3:對于未編碼“中文字元”,使用request.querystring時内部調用httputility.urldecode後,由gb2312->utf-8時,

如果查不到該中文字元,預設轉成"%ufffd",是以出現不可逆亂碼。

Request 接收參數亂碼原了解析

4:解決之路

知道了原理,解決的方式也有多種多樣了:

1:全局統一為utf-8編碼,省事又省心。

2:全局指定了gb2312編碼時,url帶中文,js非編碼不可,如ext.js架構。

這種方式你隻能特殊處理,在服務端指定編碼解碼,

因為預設系統調用了一次httputility.urldecode("xxx",系統配置的編碼),

是以你再調用一次httputility.urlencode("xxx",系統配置的編碼),傳回到原始urt-8編碼參數

再用httputility.urldecode("xxx",utf-8),解碼即可。

5:其它說明:預設對進行一次解碼的還包括uri屬性,而request.rawurl則為原始參數

版權聲明:本文原創發表于部落格園,作者為路過秋天,原文連結:

http://www.cnblogs.com/cyq1162/archive/2010/11/29/1891124.html

繼續閱讀