近来遇到一麻烦的问题,就是将utf的数据要提交到外站,比如说支付宝,网银,顺便鄙视下网银的技术服务,一开始还说加个encoding=utf-8就能解决问题,感觉他们好像有数据处理接口一样,结果不行,耽误我时间,然后还满会推卸责任的,发个搜索出来.net的转换程序给我看,要搜索我自己不会么?
反正总得对客户负责,我就只有自己动手找啦。
网上找了找,全部先放着,方便以后来找。
第一个
<%
'个人代码风格注释(变量名中第一个小写字母表表示变量类型)
'i:为Integer型;
's:为String;
Function U2UTF8(Byval a_iNum)
Dim sResult,sUTF8
Dim iTemp,iHexNum,i
iHexNum = Trim(a_iNum)
If iHexNum = "" Then
Exit Function
End If
sResult = ""
If (iHexNum < 128) Then
sResult = sResult & iHexNum
ElseIf (iHexNum < 2048) Then
sResult = ChrB(&H80 + (iHexNum And &H3F))
iHexNum = iHexNum \ &H40
sResult = ChrB(&HC0 + (iHexNum And &H1F)) & sResult
ElseIf (iHexNum < 65536) Then
sResult = ChrB(&H80 + (iHexNum And &H3F))
iHexNum = iHexNum \ &H40
sResult = ChrB(&H80 + (iHexNum And &H3F)) & sResult
iHexNum = iHexNum \ &H40
sResult = ChrB(&HE0 + (iHexNum And &HF)) & sResult
End If
U2UTF8 = sResult
End Function
Function GB2UTF(Byval a_sStr)
Dim sGB,sResult,sTemp
Dim iLen,iUnicode,iTemp,i
sGB = Trim(a_sStr)
iLen = Len(sGB)
For i = 1 To iLen
sTemp = Mid(sGB,i,1)
iTemp = Asc(sTemp)
If (iTemp>127 OR iTemp<0) Then
iUnicode = AscW(sTemp)
If iUnicode<0 Then
iUnicode = iUnicode + 65536
End If
Else
iUnicode = iTemp
End If
sResult = sResult & U2UTF8(iUnicode)
Next
GB2UTF = sResult
End Function
'调用方法
Response.BinaryWrite(GB2UTF("中国人"))
%>
第二个
- <%
- '用途:將UTF-8編碼漢字轉換為GB2312碼,兼容英文和數字
- '用法:Response.write UTF2GB("%E9%83%BD%E5%B8%82%E6%83%85%E7%B7%A3 %E6%98%9F%E5%BA%A7")
- function UTF2GB(UTFStr)
- for Dig=1 to len(UTFStr)
- if mid(UTFStr,Dig,1)="%" then
- if len(UTFStr) >= Dig+8 then
- GBStr=GBStr & ConvChinese(mid(UTFStr,Dig,9))
- Dig=Dig+8
- else
- GBStr=GBStr & mid(UTFStr,Dig,1)
- end if
- else
- GBStr=GBStr & mid(UTFStr,Dig,1)
- end if
- next
- UTF2GB=GBStr
- end function
- function ConvChinese(x)
- A=split(mid(x,2),"%")
- i=0
- j=0
- for i=0 to ubound(A)
- A(i)=c16to2(A(i))
- next
- for i=0 to ubound(A)-1
- DigS=instr(A(i),"0")
- Unicode=""
- for j=1 to DigS-1
- if j=1 then
- A(i)=right(A(i),len(A(i))-DigS)
- Unicode=Unicode & A(i)
- else
- i=i+1
- A(i)=right(A(i),len(A(i))-2)
- Unicode=Unicode & A(i)
- end if
- next
- if len(c2to16(Unicode))=4 then
- ConvChinese=ConvChinese & chrw(int("&H" & c2to16(Unicode)))
- else
- ConvChinese=ConvChinese & chr(int("&H" & c2to16(Unicode)))
- end if
- next
- end function
- function c2to16(x)
- i=1
- for i=1 to len(x) step 4
- c2to16=c2to16 & hex(c2to10(mid(x,i,4)))
- next
- end function
- function c2to10(x)
- c2to10=0
- if x="0" then exit function
- i=0
- for i= 0 to len(x) -1
- if mid(x,len(x)-i,1)="1" then c2to10=c2to10+2^(i)
- next
- end function
- function c16to2(x)
- i=0
- for i=1 to len(trim(x))
- tempstr= c10to2(cint(int("&h" & mid(x,i,1))))
- do while len(tempstr)<4
- tempstr="0" & tempstr
- loop
- c16to2=c16to2 & tempstr
- next
- end function
- function c10to2(x)
- mysign=sgn(x)
- x=abs(x)
- DigS=1
- do
- if x<2^DigS then
- exit do
- else
- DigS=DigS+1
- end if
- loop
- tempnum=x
- i=0
- for i=DigS to 1 step-1
- if tempnum>=2^(i-1) then
- tempnum=tempnum-2^(i-1)
- c10to2=c10to2 & "1"
- else
- c10to2=c10to2 & "0"
- end if
- next
- if mysign=-1 then c10to2="-" & c10to2
- end function
- %>
第三个看看下面的文字,就知道了,在后来我加了这个,程序顶端
<%Session.CodePage=65001%>
<%@ codepage=936%>简体中文
<%@ codepage=950%>繁体中文
<%@ codepage=65001%>UTF-8
codepage指定了IIS按什么编码读取传递过来的串串(表单提交,地址栏传递等)。
出乱码的原因也就是网站要整合的时候模块编码不一样引起的。
不要转换任何模块网页的编码该utf-8的还是utf-8,该Gb22312的还是Gb2312
于是我将GB2312模块的conn.asp文件中加入了以下这段代码
<%@LANGUAGE="VBSCRIPT" CODEPAGE="936"%>
<%Session.CodePage=936%>
一切OK!
同样在在Utf-8模块的包文件(如conn.asp,但是要注意conn.asp必须是在第一行调用)最前面加上
<%@LANGUAGE="VBSCRIPT" CODEPAGE="65001"%>
<%Session.CodePage=65001%>
第四个
用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>