URL 编码

HTTP 请求参数,必须使用请求参数名称与请求参数值,中间以等号(=)表示成对关系,现在问题来了,如果请求参数值本身包括=符号怎么办?又或许你想发送的请求 参数值是「http://openhome.cc」这个值呢?假设是GET请求,你不能直接这么在网址列上键入:

  • http://openhome.cc/addBookmar.do?url=http://openhome.cc

在URI的规范中定义了一些保留字符(Reserved character,像是「:」、「/」、「?」、「&」、「=」、「@」、「%」等字符,在URI中都有它的作用,如果你要在请求参数上表达URI中的保留字符,必须在%字符之后以十六进制数值表示方式,来表示该字符的八个位数值。

例如,「:」字符真正储存时的八个位为00111010,用十六进制数值来表示则为3A,所以必须使用「%3A」来表示「:」,「/」字符储存时的八个 位为00101111,用十六进制表示则为2F,所以必须使用「%2F」来表示「/」字符,所以想发送的请求参数值是「http: //openhome.cc」的话,则必须使用以下格式:

  • http://openhome.cc/addBookmar.do?url=http%3A%2F%2Fopenhome.cc

这是URI规范中的百分比编码(Percent-Encoding,也就是俗称的URI编码URL编码。如果你想得知,某个字符的URL编码为何,在Java中可以使用java.net.URLEncoder类别的静态encode()方法来为我们作这个编码的动作(相对地,要译码则是使用java.net.URLDecoder的静态decode()方法)。例如:

String text = URLEncoder.encode("http://openhome.cc ", "ISO-8859-1");

知道这些有什么用?例如,你想给某人一段URL,让他可以直接点选就可以连到你想要让他看到的网页,你贴给他的URL在请求参数部份就要注意URL编码。

不过在URI之前,HTTP在GET、POST时也对保留字作了规范,这与URI规范的保留字有所差别,其中一个差别就是在URI规范中,空格符是编码为%20,而在HTTP规范中空白是编码为「+」,java.net.URLEncoder类别的静态方法encode()产生的字符串,空格符就是编码为「+」。

另一个差别就是,URI规范的URL编码,针对的是字符UTF-8编码的八个位数值,如果请求参数都是ASCII字符,那没什么问题,因为在UTF-8编码在ASCII字符的编码部份是兼容的,也就是使用一个字节,编码方式就如先前所述。
但在非ASCII字符方面,例如中文,在UTF-8的编码下,会使用三个字节来表示。例如「林」这个字在UTF-8编码下的三个字节,对应至十六进制 数值表示就是E6、9E、97,所以在URI规范下,请求参数中要包括「林」这个中文,表示方式就是「%E6%9E%97」。例如:

  • http://openhome.cc/addBookmar.do?lastName=%E6%9E%97

OK!有些人会直接打开浏览器键入以下的内容,告诉我:「URL也可以直接打中文啊!」

不过你可以将网址列复制,贴到纯文本档案中,你就会看到URI编码的结果,这其实是现在的浏览器很聪明,会自动将上述的URI编码显示为中文。无论如何,在URI规范上若如上发送请求参数,伺服端处理请求参数时,必须使用UTF-8编码来取得正确的「林」字符。

然而在HTTP规范下的URL编码,并不限使用UTF-8,例如在一个BIG5网页中,若窗体若使用GET发送「林」这个中文字,则网址列会出现:

  • http://openhome.cc/addBookmar.do?lastName=%AA%4C

这是因为「林」这个中文字的BIG5编码为两个字节,以十六进制表示的话,则分别为「AA」、「4C」,如果你透过窗体发送,由于网页是BIG5编码, 则浏览器会自动将「林」编码为「%AA%4C」,伺服端处理请求参数时,就必须指定BIG5编码,以取得正确的「林」汉字字符。

若使用java.net.URLEncoder类别的静态encode()方法来为我们作这个编码的动作,则可以如下得到「%AA%4C」的结果:

  • String text = URLEncoder.encode(" ", "BIG5");

同理可推,如果网页是UTF-8编码,而你透过窗体发送,则浏览器会自动将「林」编码为「%E6%9E%97」。若使用java.net.URLEncoder类别的静态encode()方法来为我们作这个编码的动作,则可如下得到「%E6%9E%97」的结果:

String text = URLEncoder.encode("", "UTF-8");
这些是对于URL编码的必要认识,当你发送窗体、使用Tomcat等容器或是Ajax等时,都要有这个基本认识,才能进一步处理所遇到的乱码问题。

本文来源:openhome.cc


如果给你带来帮助,欢迎微信或支付宝扫一扫,赞一下。