解UrlPathEncode的字符串的噩梦
解UrlPathEncode的字符串的噩梦
我个人比较喜欢用gb2312做网站,web.config中一直都是使用:<globalization requestEncoding="gb2312" responseEncoding="gb2312" />
然后,噩梦便开始了……
做一个最简单的页面:
Response.Write(Server.UrlDecode(Server.UrlPathEncode("两性")) & "<hr>")
Response.Write(HttpUtility.UrlDecode(Server.UrlPathEncode("两性"), Encoding.UTF8) & "<hr>")
%>
因为做了全局设定为gb2312,所以
Server.UrlDecode(String)
实际上是等价于
HttpUtility.UrlDecode(Server.UrlPathEncode(String), Encoding.GetEncoding("gb2312"))
但是,该死的Server.UrlPathEncode(String)永远是将传入的字符串按照utf-8去编码,“两性”对应的编码为:
%e4%b8%a4%e6%80%a7
试试google的解码:http://www.google.com/search?q=%e4%b8%a4%e6%80%a7
google的解码是完全正确的。
但是,在页面编码为gb2312的情况下:
Server.UrlDecode(Server.UrlPathEncode("两性"))
出来之后是乱码,因为Server.UrlDecode出来的是一个utf-8编码的字符串,手动IE编码为utf-8时,是可以看到“两怀”的。
但是,如果是“两性人”的话,则可以正确显示。
尝试过N种字符串,在大部分情况下,偶数个中文都可以正确显示,比方说“数据”,奇数个中文则最后一个字会被砍掉,比方说,“数据库”会变成“数据”。
我前面用“两性”做例子,是因为“两性”是偶数个中文,但是无法正确显示,而相应的“两性人”是奇数个中文,但却可以正常显示。(“人两性”,“性两人”等等也都是会出错。)
编码是正确的,只是,解码有时会出错。
我浪费了无数的时间,企图将这个utf-8的字符串转换为gb2312的格式;都是徒劳的。
我得出来的结果是,UrlDecode这个函数有bug,而且,这个bug似乎很有普遍性。
asp并没有提供UrlDecode的系统函数,我所找到的两个版本的asp UrlDecode函数似乎也都存在类似的问题。
夸张的是看看下面的帖子:
http://www.matrix.org.cn/forum_view.asp?forum_id=1&view_id=14847
在jsp中:http://localhost:8700/acweb/executereport.do?fileName=/批处理摸版本/三参数设置.vtf;1
String fileName=request.getParameter("fileName");
fileName= new String(fileName.getBytes("ISO8859-1"), "utf-8");
结果显示fileName为:/批处理摸版本/三参数设, 丢失:置.vtf;1
将“/批处理摸版本/三参数设置.vtf;1”在asp.net中使用Server.UrlPathEncode之后再Server.UrlDecode,出现了跟jsp一样的错误解码!
据http://dev.csdn.net/article/50/50455.shtm说:“MS之前犯的著名URL解码错误”
但是,为什么同样的错误Sun也犯?
Well,在asp.net中,不要使用Server.UrlDecode,使用HttpUtility.UrlDecode并使用相应的encoding参数便可以解决问题。
不过,要正确获得:http://localhost/try.aspx?s=%e4%b8%a4%e6%80%a7
还是要浪费一下时间,使用
Request.QueryString(0)
获得的字符串“%e4%b8%a4%e6%80%a7”已经被自动错误解码为utf-8的“两怀”了。
我使用的是类似:
tw = Mid(Request.RawUrl, 15, Request.RawUrl.Length - 13)
的方法来直接获得“%e4%b8%a4%e6%80%a7”,然后再使用HttpUtility.UrlDecode将其解码。
呼呼……在google的时候,几乎没有google出来比较详尽的说明这个解码错误的问题的东西,而且,遇到这样问题的程序员大多数都是在做jsp或者是wap开发的……敢情,做asp.net的,都没有遇到过这样的问题么?