URL特殊字符和JS编码解码方法
前言
我们在操作 URL
的时候经常需要处理其中的特殊字符,因为在 URL
中有很多字符是有特殊意义的,比如 ?
,&
,=
等等,如果在处理 URL
的时候不对这些特殊字符进行转义,那么浏览器很可能会错误解析 URL
,所以一般的编程语言都提供了对 URL
进行编码解码的 API
,在 JS
中也有对应的方法 encodeURI
,decodeURI
和 encodeURIComponent
,decodeURIComponent
。
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
)不同部分的分界符;未保留字符没有这些特殊含义。百分号编码把保留字符表示为特殊字符序列。
- 保留字符:
*
'
(
)
;
:
@
&
=
+
$
,
/
?
#
[
]
(RFC 3986 section 2.2 保留字符 (2005年1月)) -
未保留字符:
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
的方法,encodeURI
,decodeURI
和 encodeURIComponent
和 decodeURIComponent
。两组方法功能一样,都是用来对 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
进制数。