“被解码的 URI 不是合法的编码” 的问题解决

来源:互联网 发布:奇兔刷机软件怎么卸载 编辑:程序博客网 时间:2024/04/29 10:44

同事用prototype.js做ajax应用的时候,因GET请求中含有中文参数导致脚本运行时总是提示“被解码的 URI 不是合法的编码” ,来问我求解。这个问题跟url编码有关是肯定的了,但具体调试中,却还是碰了些麻烦,走了点弯路,好在还是顺利解决了。同事试了直接传未编码的中文参数,不行;又试了escape编码,不行。我想,换个URLEncode函数应该就OK了吧,没想到还是不行,错误依旧。经过一番alert / prompt / write 之后,疑问被确定在了那个大大的prototype.js文件上。(这个js框架被比较多的人用,但是我不喜欢用,以前也没去阅读它。)出错的脚本行最终被定位到一句调用decodeURIComponent方法的地方,找到了就好办了,我不想去改prototype.js了,干脆写个自己的decodeURIComponent覆盖它。查了文档知道JScript 5.5 新增的以下4个跟URI编码解码相关的函数:
    encodeURI,decodeURI,encodeURIComponent,decodeURIComponent

测试发现,这里的4个函数(方法)和Java中的类似,都是以Unicode标准进行编码解码的,也就是说将汉字视为3字节进行处理,一个汉字编码后变为类似的 %hh%hh%hh 的形式,相应的,解码函数的参数也必须复合编码结果的格式,二者可逆,否则就会报错“被解码的 URI 不是合法的编码” 。而我们程序中比较常用的GB2312, GBK, UTF-8处理中文都是2字节的,这是导致问题的根源。例:在编码为GBK的ASP中,使用Server.URLEncode("中")的结果是%D6%D0,但在客户端js里encodeURI("中") encodeURIComponent("中")的结果是%E4%B8%AD ,而如果把%D6%D0传给decodeURIdecodeURIComponent ,就会报错“被解码的 URI 不是合法的编码” 。

  不想改prototype.js的话,自己写函数覆盖上面4个方法的默认实现。下面是我写的代码。供参考。

<script language="vbscript">
Function URLEncode(str)

   
Dim s,c,a,t

   
For i=1 To Len(str)

       
c = Mid(str,i,1)

       
a = ASC(c)

       
If a<0 OR a>255 Then

           
t=Hex(a)

           
While len(t) mod 2 > 0

               
t = "0" & t

           
Wend

           
For j=1 To len(t)-1 Step 2

               
s = s & "%" & Mid(t,j,2)

           
Next

       
ElseIf a=32 Then

           
s = s & "+"

       
ElseIf (a>=48 and a<=57) or (a>=65 and a<=90) or (a>=97 and a<=122) Then

           
s = s & c

       
ElseIf a>0 and a<16 Then

           
s = s & "%0" & Hex(a)

       
ElseIf a>=16 and a<256 Then

           
s = s & "%" & Hex(a)

       
Else

           
s = s & c

       
End If

   
Next

   
URLEncode = s

End Function


Function URLDecode(input)

   
Dim str,code,a(3),b(1)

   
str=""

   
code=input

   
code=Replace(code,"+"," ")

   
Const hexstr = "0123456789ABCDEF"

   
While len(code)>0

       
If InStr(code,"%")>0 Then

           
str = str & Mid(code,1,InStr(code,"%")-1)

           
code = Mid(code,InStr(code,"%"))

           
a(0) = UCase(Mid(code,2,1))

           
a(1) = UCase(Mid(code,3,1))

           
If a(1)<>"" And InStr(hexstr,a(0))>0 And InStr(hexstr,a(1))>0 Then

               
b(0) = Eval("&H" & a(0) & a(1))

               
If b(0)>127 And Mid(code,4,1)="%" And len(code)>=6 Then

                   
a(2) = UCase(Mid(code,5,1))

                   
a(3) = UCase(Mid(code,6,1))

                   
If a(3)<>"" And InStr(hexstr,a(2))>0 And InStr(hexstr,a(3))>0 Then

                       
b(1) = Eval("&H" & a(2) & a(3))

                       
str = str & chr(b(0)*256+b(1))

                       
code = Mid(code,7)

                   
Else

                       
str = str & "%"

                       
code = Mid(code,2)

                   
End If

               
Else

                   
str = str & chr(b(0))

                   
code = Mid(code,4)

               
End If

           
Else

               
str = str & "%"

               
code = Mid(code,2)

           
End If

       
Else

           
str = str & code

           
code = ""

       
End If

   
Wend

   
URLDecode = str

End Function

</script>

<script language="javascript">

function encodeURIComponent(code){

   
return URLEncode(code);

}

function decodeURIComponent(code){

   
return URLDecode(code);

}

function encodeURI(code){

   
return URLEncode(code);

}

function decodeURI(code){

   
return URLDecode(code);

}

</script>