URL特殊字符和JS编码解码方法

Clloz · · 5,239次浏览 ·

前言

我们在操作 URL 的时候经常需要处理其中的特殊字符,因为在 URL 中有很多字符是有特殊意义的,比如 ?&=等等,如果在处理 URL 的时候不对这些特殊字符进行转义,那么浏览器很可能会错误解析 URL,所以一般的编程语言都提供了对 URL 进行编码解码的 API,在 JS 中也有对应的方法 encodeURIdecodeURIencodeURIComponentdecodeURIComponent

escape 方法已经从标准中移除,虽然有些浏览器还支持,但是尽量使用上面的方法。

URL编码

URL 编码也称作百分号编码 Percent-encoding,是对我们在 HTTP 请求中的 URL 实行的编码机制。因为我们的资源路径中的字符很有可能是在 URL 中有特殊意义的字符,比如我在本地保存一个文件名叫 test test.txt,中间有一个空格,当我把这个文件上传到服务器比如说阿里云 oss 中的时候,如果我要复制这个资源的路径就会编程 https://cdn1.clloz.com/test%20test.txt,我们的空格被转义称为 %20(这里的百分号有点像我们平常用来转义的 \ ),如果不进行转义,浏览器无法明白这个 URL 到底是什么意思。我们对资源或者目录的命名是可以包含任意字符,比如空格,?甚至是各种不同的语言的字符编码,为了能让我们在请求资源的时候有一个统一的标准,必须对 URL 进行编码。

再举两个例子:例如 URL 参数字符串中使用 key=value 键值对这样的形式来传参,键值对之间以 & 符号分隔,如 /s?q=abc&ie=utf-8。如果你的 value 字符串中包含了 = 或者 &,那么势必会造成接收URL的服务器解析错误,因此必须将引起歧义的 &= 符号进行转义,也就是对其进行编码。

又如,URL 的编码格式采用的是 ASCII 码,而不是 Unicode,这也就是说你不能在 URL 中包含任何非 ASCII 字符,例如中文。否则如果客户端浏览器和服务端浏览器支持的字符集不同的情况下,中文可能会造成问题。

URL中的字符

URL 中的字符分为保留字符和未保留字符,保留字符是那些具有特殊含义的字符,例如:斜线字符用于URL(或 URI )不同部分的分界符;未保留字符没有这些特殊含义。百分号编码把保留字符表示为特殊字符序列。

  1. 保留字符: * ' ( ) ; : @ & = + $ , / ? # [ ]RFC 3986 section 2.2 保留字符 (2005年1月))

  2. 未保留字符:A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 - _ . ~RFC 3986 section 2.2 保留字符 (2005年1月))

URI 中的其它字符必须用百分号编码。

因为保留字符在 URL 中具有特殊的含义,所以当我们的路径中使用保留字符作为普通字符的时候就必须进行转义,其实保留字符的转义非常简单,就是在对应保留字符的 ASCII 码对应的十六进制数前面加上转义字符 % 即可。对于非 ASCII 字符, 需要转换为 UTF-8 字节序, 然后每个字节按照上述方式表示。

例如,/, 如果用作 URI 的路径成分的分界符, 则是具有特殊含义的保留字符. 如果该字符需要出现在 URI 一个路径成分的内部, 则三字符序列%2F%2f 就用于代替原本的 / 出现在该 URI 路径成分的内部。

保留字符 编码
空格 %20
! %21
" %22
# %23
$ %24
% %25
& %26
' %27
( %28
) %29
* %2A
+ %2B
,  %2C
/ %2F
: %3A
;  %3B
<  %3C
=  %3D
> %3E
? %3F
@  %40
[ %5B
\  %5C
] %5D
|  %7C

JS中的URL编码解码方法

JS 中提供了两组用来编码解码 URL 的方法,encodeURIdecodeURIencodeURIComponentdecodeURIComponent。两组方法功能一样,都是用来对 URI 进行编码或者解码,不同的是对编码字符的范围有所不同,encodeURI 的范围要比 encodeURIComponent 小一些。

encodeURI 会转义除以下字符的所有字符:

类型 包含
保留字符 ; , / ? : @ & = + $
非转义的字符 A-Z a-z 0-9 - _ . ! ~ * ' ( )
数字符号 #

encodeURIComponent 会转义除了转义除了字母数字().!~*'-_ 之外的所有字符。

对于非 ASCII 码的字符,这两个方法都会将对应的字符的多字节的 UTF-8 编码转义成单字节的 16 进制数,比如 你好吗UTF-8 编码是 E4BDA0 E5A5BD E59097 就会被这两个方法转义为 %E4%BD%A0 %E5%A5%BD %E5%90%97,每个字都是三个字节,就被转义为三个两位的 16 进制数。

参考文章

  1. 网址URL中特殊字符转义编码
  2. 百分号编码
  3. ES5/标准 ECMAScript 内置对象

Clloz

人生をやり直す

发表评论

电子邮件地址不会被公开。 必填项已用*标注

我不是机器人*

 

00:00/00:00