用XMLHTTP Post/Get HTML頁面時的中文亂碼問題之完全Script解決方案 (轉)

gugu99發表於2007-12-28
用XMLHTTP Post/Get HTML頁面時的中文亂碼問題之完全Script解決方案 (轉)[@more@]

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

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

Part I Post中文內容

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



如果把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嘛當然就是這個樣子了。既然這樣,那我們也知道該怎麼辦了——自己做轉換,程式碼見下:

<BR>Function URLEncoding(vstrIn)<BR>&nbsp;strReturn = ""<BR>&nbsp;For i = 1 To Len(vstrIn)<BR>&nbsp;ThisChr = Mid(vStrIn,i,1)<BR>&nbsp;If Abs(Asc(ThisChr)) < &HFF Then<BR>&nbsp;strReturn = strReturn & ThisChr<BR>&nbsp;Else<BR>&nbsp;innerCode = Asc(ThisChr)<BR>&nbsp;If innerCode < 0 Then<BR>&nbsp;innerCode = innerCode + &H10000<BR>&nbsp;End If<BR>&nbsp;Hight8 = (innerCode&nbsp;And &HFF00) &HFF<BR>&nbsp;Low8 = innerCode And &HFF<BR>&nbsp;strReturn = strReturn & "%" & Hex(Hight8) &&nbsp;"%" & Hex(Low8)<BR>&nbsp;End If<BR>&nbsp;Next<BR>&nbsp;URLEncoding = strReturn<BR>End Function<BR><BR>strA = URLEncoding("submit1=Submit&text1=中文")<BR>oReq = CreateObject("MSXML2.XMLHTTP")<BR>oReq.open "POST","asp",false<BR>oReq.setRequestHeader "Content-Length",Len(strA)<BR>oReq.setRequestHeader "CONTENT-TYPE","application/x-www-form-urlencoded"<BR>oReq.send strA<BR>


(在這裡俺把前面的的程式碼改成了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!

程式碼見下:
<BR>Function URLEncoding(vstrIn)<BR>&nbsp;strReturn = ""<BR>&nbsp;For i = 1 To Len(vstrIn)<BR>&nbsp;ThisChr = Mid(vStrIn,i,1)<BR>&nbsp;If Abs(Asc(ThisChr)) < &HFF Then<BR>&nbsp;strReturn = strReturn & ThisChr<BR>&nbsp;Else<BR>&nbsp;innerCode = Asc(ThisChr)<BR>&nbsp;If innerCode < 0 Then<BR>&nbsp;innerCode = innerCode + &H10000<BR>&nbsp;End If<BR>&nbsp;Hight8 = (innerCode&nbsp;And &HFF00) &HFF<BR>&nbsp;Low8 = innerCode And &HFF<BR>&nbsp;strReturn = strReturn & "%" & Hex(Hight8) &&nbsp;"%" & Hex(Low8)<BR>&nbsp;End If<BR>&nbsp;Next<BR>&nbsp;URLEncoding = strReturn<BR>End Function<BR><BR>Function bytes2BSTR(vIn)<BR>&nbsp;strReturn = ""<BR>&nbsp;For i = 1 To LenB(vIn)<BR>&nbsp;ThisCharCode = AscB(Mi(vIn,i,1))<BR>&nbsp;If ThisCharCode < &H80 Then<BR>&nbsp;strReturn = strReturn & Chr(ThisCharCode)<BR>&nbsp;Else<BR>&nbsp;NextCharCode = AscB(MidB(vIn,i+1,1))<BR>&nbsp;strReturn = strReturn & Chr(CLng(ThisCharCode) * &H100 + CInt(NextCharCode))<BR>&nbsp;i = i + 1<BR>&nbsp;End If<BR>&nbsp;Next<BR>&nbsp;bytes2BSTR = strReturn<BR>End Function<BR><BR>strA = URLEncoding("submit1=Submit&text1=中文")<BR>oReq = CreateObject("MSXML2.XMLHTTP")<BR>oReq.open "POST","asp",false<BR>oReq.setRequestHeader "Content-Length",Len(strA)<BR>oReq.setRequestHeader "CONTENT-TYPE","application/x-www-form-urlencoded"<BR>oReq.send strA<BR>alert bytes2BSTR(oReq.responseBody)<BR>


嘿嘿,是不是很簡單啊,用這個再試試看?一切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,看來未必是個好主意。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-995951/,如需轉載,請註明出處,否則將追究法律責任。

相關文章