AJAX傳輸資料的中文亂碼之完全解決方案

來源:互聯網
上載者:User

[解決方案一]

以前我曾經貼過一篇用XMLHTTP Post Form 的文章,那裡的代碼中我Post E文的Value毫無問題,但是後來發現Post含有中文的表單時會出現亂碼,原因當然是UTF-8 和GB2312 之間的轉換問題了!TNND,打倒GB2312!大家都用UTF8多好。

用XMLHTTP Post Form時的表單亂碼有兩方面的原因——Post表單資料時中文亂碼;伺服器Response被XMLHTTP不正確編碼引起的亂碼。換句話說,本文主要解決兩個問題——怎樣正確Post中文內容&怎樣正確顯示得到的中文內容。

Part I Post中文內容

先看看E文的表單是怎麼提交的:

<SCRIPT language="JavaScript">
strA = "submit1=Submit&text1=scsdfsd";
var oReq = new ActiveXObject("MSXML2.XMLHTTP");
oReq.open("POST","http://ServerName/VDir/TstResult.asp",false);
oReq.setRequestHeader("Content-Length",strA.length);  
oReq.setRequestHeader("CONTENT-TYPE","application/x-www-form-urlencoded");
oReq.send(strA);
</ScRIPT>

如果把strA = "submit1=Submit&text1=scsdfsd";換成:
strA = "submit1=Submit&text1=中文";

你會發現提交上去的東東根本不對,ASP中Request.Form("Text1")根本取不到值。俺用Request.BinaryRead把一個HTML Form中的Post內容寫出來看了看,才發現問題——Form提交時也要編碼的,編碼後的中文是類似於%??%??的逸出字元,比如“中文”就被編碼為:%D6%D0%CE%C4。呵呵,也怪俺笨,人家CONTENT-TYPE裡明明寫的清清楚楚——application/x-www-form-urlencoded,urlencoded嘛當然就是這個樣子了。既然這樣,那我們也知道該怎麼辦了——自己做轉換,代碼見下:

<SCRIPT language="VBScript">
Function URLEncoding(vstrIn)
    strReturn = ""
    For i = 1 To Len(vstrIn)
        ThisChr = Mid(vStrIn,i,1)
        If Abs(Asc(ThisChr)) < &HFF Then
            strReturn = strReturn & ThisChr
        Else
            innerCode = Asc(ThisChr)
            If innerCode < 0 Then
                innerCode = innerCode + &H10000
            End If
            Hight8 = (innerCode  And &HFF00)\ &HFF
            Low8 = innerCode And &HFF
            strReturn = strReturn & "%" & Hex(Hight8) &  "%" & Hex(Low8)
        End If
    Next
    URLEncoding = strReturn
End Function

strA = URLEncoding("submit1=Submit&text1=中文")
oReq = CreateObject("MSXML2.XMLHTTP")
oReq.open "POST","http://ServerName/VDir/TstResult.asp",false
oReq.setRequestHeader "Content-Length",Len(strA)
oReq.setRequestHeader "CONTENT-TYPE","application/x-www-form-urlencoded"
oReq.send strA
</ScRIPT>

(在這裡俺把前面的JavaScript的代碼改成了VBScript,不是吃飽了撐的沒事幹,原因見後)

Part II.正確顯示得到的中文內容

OK,如果你在Server端把Form的內容寫到資料庫/檔案的話,你在那裡看到的中文毫無問題,但是,假如你想看看Server的Response——問題來了:如果Response的結果不是XML,XMLHTTP.responseXML裡當然是不會有東東的,那就用responseText好了,在代碼的最後加一句:

alert(oReq.responseText)
看看俺們辛勤勞動的結果  :P

但是但是.....怎麼所有的中文全變成了方格? (我打不出來,有興趣自己去試,也不用Post,Get一個含有中文的網頁就可以發現了。)

原因很簡單:XMLHTTP得到Response時假定Response是UTF8編碼的,如果Response是XML,那還可以通過encoding來指定編碼,但HTML就不行了。(見鬼的GB2312,再次打倒!)所以它把含GB2312編碼的HTML當成UTF8格式,不出錯才有鬼!

不過好在還有補救的辦法:XMLHTTP的responseBody 屬性裡包含的可是未解碼的Resonse——"a raw undecoded bytes as received directly from the server" :),唯一的問題是,responseBody返回的是一個unsigned bytes數組,我們怎麼去訪問它,怎麼把它轉換成BSTR?

這就是為什麼我在上面把代碼改成VBScript的原因——VBScript Can do it,but JavaScript Cannot!

代碼見下:
<SCRIPT language="VBScript">
Function URLEncoding(vstrIn)
    strReturn = ""
    For i = 1 To Len(vstrIn)
        ThisChr = Mid(vStrIn,i,1)
        If Abs(Asc(ThisChr)) < &HFF Then
            strReturn = strReturn & ThisChr
        Else
            innerCode = Asc(ThisChr)
            If innerCode < 0 Then
                innerCode = innerCode + &H10000
            End If
            Hight8 = (innerCode  And &HFF00)\ &HFF
            Low8 = innerCode And &HFF
            strReturn = strReturn & "%" & Hex(Hight8) &  "%" & Hex(Low8)
        End If
    Next
    URLEncoding = strReturn
End Function

Function bytes2BSTR(vIn)
    strReturn = ""
    For i = 1 To LenB(vIn)
        ThisCharCode = AscB(MidB(vIn,i,1))
        If ThisCharCode < &H80 Then
            strReturn = strReturn & Chr(ThisCharCode)
        Else
            NextCharCode = AscB(MidB(vIn,i+1,1))
            strReturn = strReturn & Chr(CLng(ThisCharCode) * &H100 + CInt(NextCharCode))
            i = i + 1
        End If
    Next
    bytes2BSTR = strReturn
End Function

strA = URLEncoding("submit1=Submit&text1=中文")
oReq = CreateObject("MSXML2.XMLHTTP")
oReq.open "POST","http://ServerName/VDir/TstResult.asp",false
oReq.setRequestHeader "Content-Length",Len(strA)
oReq.setRequestHeader "CONTENT-TYPE","application/x-www-form-urlencoded"
oReq.send strA
alert bytes2BSTR(oReq.responseBody)
</ScRIPT>

嘿嘿,是不是很簡單啊,用這個再試試看?一切OK!

(順便說說byte(),這個東東在VBScript裡的表現只能用妖來形容——對它調用VarType 返回8209——vbArray + vbByte,用LBound、UBound能拿到數組的上界下界,但是就是不能用name(i)的形式訪問,搞得我以為在Script雷根本沒法處理這種類型,在bytes2BSTR函數裡可以看到我是把它當成String來處理的——LenB/MidB什麼的,發現這點純屬意外——我開始往這個函數裡傳的是XMLHTTP.responseText,想一個Byte一個Byte地看看裡面到底有點什麼,後來一時性起把responseText改成responseBody,結果就中獎了,哈哈)

最後的廢話:
1、以上代碼在MSXML Parser 3 Release+VBScript 5.5環境下通過。那位兄弟有早一點版本的Script可以幫我試試看能不能成。
2、一直以為JavaScript vs VBScript應該是JavaScript略好,所以有時候想徹底拋棄VBScript,ASP Server/Client統統用JavaScript,看來未必是個好主意。

[解決方案二]

用escape和unescape方法解決AJAX應用中的中文亂碼問題

在網上尋找關於AJAX應用中關於中文亂碼的問題,找到一個儲存資料時對編碼進行轉換的方法
原理是把資料存放區到資料庫以及把資料從資料庫取出後對資料進行編碼轉換.
前陣遇到過這樣的問題,當時沒有找到解決的方法.
現在看來這個方法應該可行,還沒試過,先記一筆!

escape 方法

描述
對 String 對象編碼以便它們能在所有電腦上可讀,
文法
escape(charstring)
charstring 參數是要編碼的 String 對象。

說明
escape 返回一個包含了 charstring 內容的新的 String 對象( Unicode 格式), 所有空格、標點、重音符號以及其他非 ASCII 字元都用 %xx 編碼代替,其中 xx 等於表示該字元的十六進位數。 例如,空格返回的是 "%20" 。
字元的值大於 255 的用 %uxxxx 格式儲存。

unescape 方法

描述
解碼用 escape 方法進行了編碼的 String 對象。
文法
unescape(charstring)
charstring 參數是要解碼的 String 對象。

說明
unescape 方法返回儲存了 charstring 內容新的 String 對象。 所有以 %xx 十六進位形式編碼的字元都用 ASCII 字元集中等價的字元代替。
以 %uxxxx 格式(Unicode 字元)編碼的字元用十六進位編碼 xxxx 的 Unicode 字元代替.

[解決方案三]

當大家用objXML.ResponseText獲得某頁面的Response.Write輸出的中文時,會顯示為亂碼,我昨天查了下資料,找到瞭解決辦法,所以貼出來。

Response.CharSet = "GB2312"

Response.Write("中文就可以正常顯示了!")

呵呵 不過我沒顯示中文,Ajax本身就是要降低伺服器的頻寬佔用的,所以我直接Response.write("1")

然後在用戶端判斷

if (objXML.ResponseText == 1)
  obj.innerHTML = "您輸入的資料不合法";

其他語言我不會  估計都是設定輸出的語言編碼為GB2312就可以了

用AJAX來GET回一個頁面時,responseText裡面的中文多半會出現亂碼,這是因為XMLHttp在處理返回的responseText的時候,是把resposeBody按UTF-8編碼進解碼考形成的,如果伺服器送出的確實是UTF-8的資料流的時候漢字會正確顯示,而送出了GBK編碼流的時候就亂了。解決的辦法就是在送出的流裡面加一個Header,指明送出的是什麼編碼流,這樣XMLHttp就不會亂搞了。

PHP:header(’Content-Type:text/html;charset=GB2312′);
ASP:Response.Charset(”GB2312″)
JSP:response.setHeader(”Charset”,”GB2312″);

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=888152

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.