URL 编码/解码
百分号编码转换,处理中文参数与特殊字符
URL 编码详解:encodeURI、encodeURIComponent 与五个最容易踩的坑
为什么需要 URL 编码
URL 的字符集是有限的(RFC 3986 只允许 ASCII 的一个子集)。任何不在允许范围内的字符——空格、中文、&、?、#——都必须先转成百分号编码:% 加两位十六进制。
关键在于,非 ASCII 字符要先按 UTF-8 编码成字节,再逐字节转百分号。中文"中"的 UTF-8 字节是 E4 B8 AD,所以编码结果是 %E4%B8%AD,而不是某个单字节值。搞错这一步(比如按 GBK 编码)是乱码的典型来源。
encodeURI 和 encodeURIComponent 的差别
这是实际开发中最容易选错的地方。两者的不转义字符集不同:
| 保留不转义的字符 | encodeURI | encodeURIComponent |
|---|---|---|
| 字母数字 | 是 | 是 |
- _ . ! ~ * ' ( ) | 是 | 是 |
URL 结构字符 ; , / ? : @ & = + $ # | 是 | 否 |
规则很简单:
- 编码整个 URL(比如要把一个地址作为参数传给另一个系统)→ 用
encodeURI,否则https://会变成https%3A%2F%2F,链接直接失效。 - 编码 URL 中的某个值(查询参数的值、路径片段)→ 用
encodeURIComponent,否则值里出现的&会被解析成参数分隔符,把后面的内容切走。
常见的真实 bug:搜索词是 a&b,用 encodeURI 之后变成 a&b 原样传过去,服务端解析出两个参数——q=a 和 b=。用 encodeURIComponent 得到 a%26b 才对。
空格:%20 还是 +
两种写法都存在,但适用的地方不同:
%20是 URL 标准里空格的编码,任何位置都合法。+只在application/x-www-form-urlencoded这种表单提交语境的查询字符串里代表空格。它属于 HTML 表单规范,不属于 URL 规范。
所以路径里的 + 就是加号本身,不是空格。把 /a+b/ 解成 /a b/ 是错的。这个工具按你的需求选择用 %20 还是 +,并会显示两种结果供对照。
五个容易踩的坑
- 重复编码。编码两次得到
%2520(因为%本身变成%25)。看到%25就该警觉:多半是多编码了一层。判断方法:解码一次看结果是否变成另一个合法的百分号序列。 - 只编码值不编码键。参数名一样可能含特殊字符,两边都要编。
- 忘了对
&和=编码。这是注入类问题的入口,也是参数错乱的根源。 - 假设服务端会自动解码。不一定。服务端框架、网关、CDN 各自可能解一层,也可能不解。传之前确认约定。
- 把
#编成%23却指望它还能当锚点。编码后的%23是字面量,不再是片段标识符。
常用字符对照
| 字符 | 编码 | 说明 |
|---|---|---|
| 空格 | %20 | 标准编码;表单语境可用 + |
& | %26 | 参数分隔符,值里必须编 |
= | %3D | 键值分隔符,值里必须编 |
? | %3F | 查询串起始符 |
# | %23 | 片段标识符起始 |
+ | %2B | 不编会被当成空格 |
% | %25 | 编码前缀自身 |
| 中文 | 每字节一个 %XX | 先 UTF-8 再逐字节编码 |
工具支持单向编码、单向解码和双向互转,粘贴 URL 或裸文本都能处理。
常见问题
encodeURI 和 encodeURIComponent 有什么区别?
前者保留 / ? & = 等 URL 结构字符,适合整条 URL;后者全部转义,适合参数值。本工具用后者。