← 返回工具箱

URL 编码完全指南:%20 与 + 的区别、中文为什么变 %E4%B8%AD

开发者工具箱 · 使用教程

一个带中文和空格的 URL,粘到浏览器里有时正常、有时 404,有时参数莫名其妙丢了。问题几乎都出在 URL 编码上。这篇文章讲清为什么要编码、编码规则是什么、以及最容易混的 %20 和 +。

一、为什么 URL 需要编码

URL 的字符集是有限的。在标准里,只有下面这些字符可以原样出现在 URL 中:

字母   A-Z a-z
数字   0-9
符号   - _ . ~
保留   ! * ' ( ) ; : @ & = + $ , / ? # [ ] %

其他字符(空格、中文、日文、emoji、各种符号)都必须转换成百分号编码:% 后面跟两位十六进制数,这两位数是那个字符的字节值。

关键点:编码的对象是字节,不是字符。所以首先要确定用哪种字符集把字符变成字节——现代标准统一用 UTF-8。

二、中文为什么变成 %E4%B8%AD

以“中”字为例:

"中"
  UTF-8 字节    E4  B8  AD
  百分号编码    %E4 %B8 %AD
  连起来        %E4%B8%AD

所以“中文”两个字编码后是 %E4%B8%AD%E6%96%87——一个汉字对应三个 %XX,因为 UTF-8 里常用汉字占 3 字节(生僻字和 emoji 是 4 字节,对应四组)。

看到一个字符变成 3 组 %XX,别慌,那是正常的 UTF-8 中文。如果变成 2 组,说明用的是 GBK——这往往就是乱码的根源。

三、%20 和 + 的区别

这是最经典的一个坑。空格的编码有两种写法,用错场景就会出问题:

写法用在哪说明
%20URL 的路径部分标准写法,任何地方都安全
+application/x-www-form-urlencoded 的查询串表单提交格式的历史遗留

具体来说:

路径里:  /my%20file.txt        ✓
          /my+file.txt         ✗ 服务器会把 + 当成字面加号

查询串:  ?q=hello%20world     ✓ 一般可用
          ?q=hello+world       ✓ 表单提交格式下,+ 表示空格
稳妥做法:一律用 %20。它不会错,而 + 是否被解释成空格取决于服务端实现。

四、双重编码

“双重编码”指数据被编码了两次,% 本身变成了 %25。看到下面这种一串 %25,说明重了:

原文         a b
一次编码     a%20b
二次编码     a%2520b      ← % 被编成了 %25

什么时候会发生:

排查方法:把可疑参数单独解码一次,看是否还有 %。还有,就是双重编码。

五、encodeURI 和 encodeURIComponent

JavaScript 里有两个容易混的函数:

函数不编码的字符用在哪
encodeURI保留 :/?#[]@!$&'()*+,;=编码整个 URL
encodeURIComponent只保留 -_!~*'()编码参数值

用错会出现什么:

// 参数里含 & 时,用 encodeURI 会毁掉参数结构
const v = "a&b";
encodeURI(v)          → "a&b"        ✗ & 没被编码,会被当成分隔符
encodeURIComponent(v) → "a%26b"      ✓

// 整个 URL 用 encodeURIComponent 会把 : / 也编码
encodeURIComponent("https://a.com/x")
  → "https%3A%2F%2Fa.com%2Fx"        ✗ 整条 URL 废了

记法很简单:编参数值用 encodeURIComponent,编整条 URL 用 encodeURI。

六、怎么用本工具

  1. 打开开发者工具箱的 URL 编码标签页
  2. 粘贴内容点「编码」,特殊字符变成 %XX
  3. 粘贴编码结果点「解码」,还原原文
  4. 遇到乱码,先确认原文是不是 UTF-8
广告位 - 适合横幅广告

七、常见问题

浏览器地址栏里中文能直接显示,为什么还要编码?
浏览器显示时会“人性化”地把编码还原成中文给你看,但实际发出的请求仍然是编码后的。如果你从地址栏复制发到别处,有些场景复制到的是显示形式,有些是编码形式,容易造成“看起来一样但不通”。
为什么我的 URL 里既有 %E4 又有 %B8 还有 %AD?
那是一个汉字的三字节,拆成了三组 %XX。UTF-8 编码下面,常用汉字一律占 3 字节,所以一个汉字 = 三组。
编码后 URL 变得很长,会影响 SEO 吗?
会有一点影响。URL 长度本身就是轻微的负面因素,而且编码后不直观。中文站点常见的做法是用英文或拼音做 slug,把中文标题放在标题标签里,而不是塞进 URL。
空格在查询串里到底会不会变成 +?
取决于服务端。按 application/x-www-form-urlencoded 解析的框架(多数后端框架的表单解析器)会把 + 当空格;而按 RFC 3986 严格解析的工具会当字面加号。这就是“同一个接口换个框架就出问题”的原因。
怎么快速判断是不是编码问题?
看三个特征:URL 里有大量 %XX;+ 出现在本该是空格的位置;%25 出现(双重编码)。命中任何一条,基本可以定位。
到底该不该对 URL 参数做两次编码?
不该,除非协议明确要求。比如把一个完整 URL 当作另一个 URL 的参数值传递时,外层编码是必要的(否则内层的 & 会破坏结构),但这是“正确的一次”,不是“多余的第二次”。判断标准:解码一次后应该得到原始可用的值。
广告位 - 适合横幅广告