在HTTP协议中,浏览器不能向服务器直接传递某些特殊字符,就必须对这些字符进行URL编码再传送。
浏览器一般会以UTF-8和ANSI(当前系统语言设置)两种方式发送URL到服务器。
例如:
在baidu中搜索中国的结果:http://www.baidu.com/s?wd=%D6%D0%B9%FA&cl=3。即[中国]被解析成:%D6%D0%B9%FA
在google中搜索中国的结果:http://www.google.com/search?hl=en&q=%E4%B8%AD%E5%9B%BD。即[中国]被解析成%E4%B8%AD%E5%9B%BD。
分析两个页面源代码。baidu使用的charset=gb2312字符集,即ANSI编码。google使用的是charset=UTF-8字符集,即UTF-8进行编码。
编码的规则:
1、空格转换成为"+"
2、0~9,a~z,A~z字符表示不变。
3、其他字符编码在以十六进制格式表示,并在每个十六进制字节上加上[%]
对[email:admin@xx.com * 中国]进行编码,在baidu搜索中验证结果为:http://www.baidu.com/s?wd=email%3Aadmin@xx.com+*+%D6%D0%B9%FA&cl=3
ASP中间对Url的编码解码可以使用Server.URLEncode和Server.UrlDecode来完成。
如何在VB中间也实现URLEncode和UrlDecode。
对[中国]编码,结果为:%D6%D0%B9%FA
'利用Ascii转换16进位制
Private Sub cmdEncode_Click()
Dim i As Integer
Dim strChar As String
Dim strMsg As String
Dim strText As String
strMsg = "中国"
For i = 1 To Len(strMsg)
strText = strText & "%" & Left(Hex(Asc(Mid(strMsg, i, 1))), 2) & "%" & Right(Hex(Asc(Mid(strMsg, i, 1))), 2)
Next
Debug.Print strText
End Sub
'利用strConv转换当前页码处理
Private Sub cmdEncode_Click()
Dim strMsg As String
Dim a() As Byte
Dim i As Integer
Dim strText As String
strMsg = "中国"
a() = StrConv(strMsg, vbFromUnicode)
For i = LBound(a) To UBound(a)
strText = strText & "%" & Right("00" & Hex(a(i)), 2)
Next
Debug.Print strText
End Sub
对[%D6%D0%B9%FA]解码,结果为:[中国]
'按Ascii进行解码
Private Sub cmdDecode_Click()
Dim strText As String
Dim strMsg As String
Dim strChar As String
Dim i As Integer
strText = "%D6%D0%B9%FA"
For i = 1 To Len(strText)
strChar = Mid(strText, i, 1)
If strChar = "%" Then
strMsg = strMsg & Chr(Val("&H" & Mid(strText, i + 1, 2) & Mid(strText, i + 4, 2)))
i = i + 5
End If
Next
Debug.Print strMsg
End Sub
'以strConv进行当前页面解码
Private Sub cmdDecode_Click()
Dim i As Long
Dim a() As Byte, vTemp As Variant
Dim strText As String
Dim strMsg As String
strText = "%D6%D0%B9%FA"
vTemp = Split(strText, "%")
ReDim a(UBound(vTemp) - 1) As Byte
For i = LBound(vTemp) + 1 To UBound(vTemp)
a(i - 1) = Val("&h" & vTemp(i))
Next
strMsg = StrConv(a, vbUnicode)
Debug.Print strMsg
End Sub
按以上规则在VB中实现URLEncode为ANSI编码方式
'进行UrlEncode编码(ANSI)
Private Function UrlEncode(strUrl As String) As String
Dim i As Integer, j As Integer
Dim a() As Byte
Dim strChar As String
Dim strText As String
strText = ""
For i = 1 To Len(strUrl)
strChar = Mid(strUrl, i, 1)
Select Case Asc(strChar)
'48 to 57代表0~9;65 to 90代表A~Z;97 to 122代表a~z
'42代表*;46代表.;64代表@;45代表-;95代表_ 此点在文最后做出说明
Case 48 To 57, 65 To 90, 97 To 122, 42, 45, 46, 64, 95
strText = strText & strChar
'空格转换成 "+", 注意的"+"会转换成"%2B"
Case 32
strText = strText & "+"
'其他字符正常转换成十六进制
Case Else
'转换成为缺省页码
a = StrConv(strChar, vbFromUnicode)
For j = LBound(a) To UBound(a)
strText = strText & "%" & Right("00" & Hex(a(j)), 2)
Next
Erase a()
End Select
Next
UrlEncode = strText
End Function
运行:Debug.Print UrlEncode("email:admin@xx.com * 中国")
结果: email%3Aadmin@xx.com+*+%D6%D0%B9%FA
'进行UrlEncode解码(ANSI)
Public Function UrlDecode(strUrl As String) As String
Dim strChar As String
Dim strText As String
Dim strTemp As String
Dim strRet As String
Dim LngNum As Long
Dim i As Integer
For i = 1 To Len(strUrl)
strChar = Mid(strUrl, i, 1)
Select Case strChar
Case "+"
strText = strText & " "
Case "%"
strTemp = Mid(strUrl, i + 1, 2) '暂时取2位
LngNum = Val("&H" & strTemp)
'>127即为汉字
If LngNum < 128 Then
strRet = Chr(LngNum)
i = i + 2
Else
strTemp = strTemp & Mid(strUrl, i + 4, 2)
strRet = Chr(Val("&H" & strTemp))
i = i + 5
End If
strText = strText & strRet
Case Else
strText = strText & strChar
End Select
Next
UrlDecode = strText
End Function
运行:Debug.Print UrlDecode("email%3Aadmin@xx.com+*+%D6%D0%B9%FA")
结果:email:admin@xx.com * 中国
需要注意的几点:
1、网络中通常会说CBK,GB2312,JIS,BIG5是字符集,而字符的储存方式叫作编码。各个国家和地区在制定编码标准的时候,“字符的集合”和“编码”一般都是同时制定的。因此,平常我们所说的“字符集”,同时也包含了“编码”的含义。
2、如果直接在IE地址栏输入:http://www.baidu.com/s?wd=中国是可以访问的,但是换作Opera浏览器则会错误。这是由于不同浏览器识对客户端的URL编码不同造成。具体可参考:浏览器发送URL的编码特性。
3、在本段在URLEncode中加入对[*],[.],[@],[-],[-]的判断。主要是显示编码以后地址栏URL的结果,如baidu搜索中admin@xx.com会依旧会解吸成为admin@xx.com.
但是地址栏的URL并不代表发送到服务器的URL ,发送到服务器的URL实际上已经被编码成为admin%40cnlaunch%2Ecom。
所以如果需要显示成地址栏的结果,可以按以上函数,如果显示大送到服务器的URL编码,可以去掉对这5个字符的Ascii判断即可。
发表于 @ 2007年09月25日 17:17:00|评论(loading...)|编辑