技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> 其他 --> 关于URL编码

关于URL编码

浏览:2993次  出处信息

    一、问题的由来

    URL就是网址,只要上网,就一定会用到。

    bg2010021101.jpg

    一般来说,URL只能使用英文字母、阿拉伯数字和某些标点符号,不能使用其他文字符号。因为网络标准RFC 1738做了硬性规定:

    "...Only alphanumerics [0-9a-zA-Z], the special characters "$-_.+!*\'()," [not including the quotes - ed], and reserved characters used for their reserved purposes may be used unencoded within a URL."

    “只有字母和数字[0-9a-zA-Z]、一些特殊符号“$-_.+!*\'(),”[不包括双引号]、以及某些保留字,才可以不经过编码直接用于URL。”

    这意味着,如果URL中有汉字,就必须编码后使用。

    但是麻烦的是,RFC 1738没有规定具体的编码方法,交给应用程序自己决定。这导致“URL编码”成为了一个混乱的领域。下面我们就来看看,它到底是怎么实现的。

    二、编码方法:网址路径

    让我们做几个试验,观察浏览器是怎么对URL编码的。

    打开IE(我用的是8.0版),输入网址“http://zh.wikipedia.org/wiki/春节”。注意,“春节”这两个字此时是网页路径的一部分。(后面将看到,如果它出现在查询字符串的部分,将是另一种编码方式。)

    bg2010021102.jpg

    查看HTTP Head,会发现IE实际查询的网址是“http://zh.wikipedia.org/wiki/%E6%98%A5%E8%8A%82”。也就是说,IE自动将“春节”编码成了“%E6%98%A5%E8%8A%82”。

    bg2010021103.png

    我们知道,“春”和“节”的utf-8编码分别是“E6 98 A5”和“E8 8A 82”,因此,“%E6%98%A5%E8%8A%82”就是按照顺序,在每个字节前加上%而得到的。(具体的转码方法,请参考我写的《字符编码笔记》。)

    在Firefox中测试,也得到了同样的结果。因此,结论一就是,网址路径的编码,用的是utf-8编码。

    三、编码方法:查询字符串

    继续做试验。在IE中输入网址“http://www.baidu.com/s?wd=春节”。注意,“春节”这两个字此时属于查询字符串,不属于网址路径。

    bg2010021104.jpg

    查看HTTP Head,会发现IE将“春节”转化成了一个乱码。

    bg2010021105.png

    切换到十六进制方式,才能清楚地看到,“春节”被转成了“B4 BA BD DA”。

    bg2010021106.png

    我们知道,“春”和“节”在GB2312编码(我的操作系统Windows XP 中文版的默认编码)中分别是“B4 BA”和“BD DA”。因此,IE实际上就是将查询字符串,以其GB2312编码的格式发送出去。

    Firefox的处理方法,略有不同。它发送的HTTP Head是“wd=%B4%BA%BD%DA”。也就是说,同样采用GB2312编码,但是在每个字节前加上了%。

    bg2010021107.png

    因此,结论二就是,查询字符串的编码,用的是操作系统的默认编码。

    四、编码方法:Get和Post

    前面说的是直接输入网址的情况,但是更常见的情况是,在已打开的网页上,直接用Get或Post方法发出HTTP请求。

    根据台湾中兴大学吕瑞麟老师的试验,这时的编码方法由网页的编码决定,也就是由HTML源码中字符集的设定决定。

      

    如果上面这一行最后的charset是UTF-8,则URL就以UTF-8编码;如果是GB2312,URL就以GB2312编码。

    举例来说,百度是GB2312编码,Google是UTF-8编码。因此,从它们的搜索框中搜索同一个词“春节”,生成的查询字符串是不一样的。

    百度生成的是%B4%BA%BD%DA,这是GB2312编码。

    bg2010021109.jpg

    Google生成的是%E6%98%A5%E8%8A%82,这是UTF-8编码。

    bg2010021108.jpg

    因此,结论三就是,GET和POST方法的编码,用的是网页的编码。

    五、Javascript函数:escape()

    为了方便编码,Javascript语言从一开始就提供了escape()函数。

    但是实际上,这个函数不能直接用于URL编码。因为它返回的不是UTF-8编码,而是Unicode编码,比如“春节”的返回结果是%u6625%u8282。

    bg2010021110.png

    具体来说,它的规则是,除了ASCII字母、数字、标点符号“@ * _ + - . /”以外,其他所有字符都会被编码。在\\u0000到\\u00ff之间的符号――也就是前256个符号――被转成%xx的形式,其余符号被转成%uxxxx的形式,其中的xx为unicode编码值。它对应的解码函数是unescape()。

    因此,“Hello World”的escape()编码就是“Hello%20World”。

    bg2010021111.png

    这里有两个地方需要注意。

    首先,Javascript内部的所有字符,都以unicode码储存。所以,无论网页的原始编码是什么,一旦被Javascript编码,就都变为unicode。

    bg2010021112.png

    其次,escape()不对“+”编码。但是我们知道,在用户提交的表单字段中,如果有空格,则会被转化为+字符。服务器处理数据的时候,会把+号处理成空格。由于这个缺陷,escape方法并不能正确地处理表单数据。ECMAScript v3已经正式废除了escape(),建议使用其他函数取代。

    六、Javascript函数:encodeURI()

    encodeURI()是Javascript中真正用来对URL编码的函数。

    它着眼于对URL进行整体编码,因此除了常见的标点符号以外,对其他一些在网址中有特殊含义的符号“; / ? : @ & = + $ , #”,也不进行编码。

    编码时,它返回utf-8编码,每个字节前加上%。

    bg2010021113.png

    它对应的解码函数是decodeURI()。

    bg2010021114.png

    需要注意的是,它不对单引号\'编码。

    七、Javascript函数:encodeURIComponent()

    这个函数与encodeURI()的区别是,只对URL的某一部分单独编码,而不对整体编码。

    因此,“; / ? : @ & = + $ , #”,这些在encodeURI()中不被编码的符号,在encodeURIComponent()中统统会被编码。至于具体的编码方法,两者是一样。

    bg2010021115.png

    它对应的解码函数是decodeURIComponent()。

    (完)

建议继续学习:

  1. 从输入 URL 到页面加载完成的过程中都发生了什么事情?    (阅读:14219)
  2. 前端要给力之:URL应该有多长?    (阅读:6903)
  3. 豆瓣的Url结构方式一览    (阅读:6446)
  4. 字符编码和中文乱码小叙    (阅读:5399)
  5. 中文编码杂谈    (阅读:4793)
  6. Hadoop的map/reduce作业输入非UTF-8编码数据的处理原理    (阅读:4442)
  7. PHP编码规范    (阅读:4198)
  8. base64_encode 和 urlencode    (阅读:3946)
  9. UTF-8编码中BOM的检测与删除    (阅读:3889)
  10. Linux screen窗口中文乱码问题    (阅读:3805)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1