用XMLHTTP Post/Get HTML頁面時的中文亂碼之完全Script解決方案
2024-07-21 02:04:26
供稿:網友
以前我曾經貼過一篇用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,看來未必是個好主意。