URL 里的空格为什么有时是加号,有时是 %20?

3 个讲解板块 · 关联 2 款站内工具 · 内容最后核对 2026-10-09

两套标准各自都对:表单编码用加号,URI 规范用 %20。

直接答案

因为这是两套不同时代的标准,各自在自己的上下文里都是正确的。RFC 3986 是 URI 规范,规定空格必须写成 %20,它在路径、查询串、片段里都有效;而 application/x-www-form-urlencoded 是更早的 HTML 表单数据格式,它规定空格写成加号,浏览器提交表单时就按这套规则编码。

关键区别在于「加号在哪儿出现」:只有在被当作表单数据解析的查询串里,加号才还原成空格;出现在路径里的加号就是字面上的加号,/files/my+file.pdf 指的就是名为 my+file.pdf 的文件。要表示真正的加号,必须写成 %2B。

同一个搜索词,从地址栏复制出来可能是 q=hello+world,从另一处复制出来却是 q=hello%20world。看起来只是风格差异,实际上两个来源动了不同的标准,谁都觉得自己是对的。

这类分歧最典型的后果不是「显示不好看」,而是参数值悄悄变了:本想传一个带加号的字符串,结果后端把它当空格;或者传了 %20,解析器又把它当字面量。想把这类 bug 一次性堵住,只需记住「谁在解这段数据,就按谁的标准编」。

1两套标准对照

同一件事,两个标准给出不同答案,这是问题的全部根源。

标准空格怎么写谁在用
RFC 3986(URI 规范)%20路径、片段、encodeURIComponent()、OAuth 签名基串、AWS SigV4
application/x-www-form-urlencoded加号HTML 表单 GET 提交、URLSearchParams、Java URLEncoder、PHP urlencode()
路径中的加号就是加号本身任何解析器,路径不会把加号还原成空格
真正的加号%2B查询串里要传字面加号必须这样写

拿不准时统一用 %20:它在任何位置都表示空格,不会因为上下文变化而产生歧义。

2中文为什么让链接变得特别长

编码是按字节做的,不是按字符做的,一个汉字要拆成好几个字节。

输入UTF-8 字节编码后占了几个字符
空格0x20%203
加号0x2B%2B(查询串里要表示字面加号时)3
「中」0xE4 0xB8 0xAD%E4%B8%AD9
「工具」6 个字节12 个字符的 %XX 串12

一个汉字在 URL 里通常膨胀成 3 倍长度,中文链接又长又难读就是这么来的。

3什么时候会踩坑,怎么排查

混用编码器与解码器是唯一的高频根因,按下面几步走一遍就能定位。

  1. 先确认这段数据是被当成 URI 解析,还是被当成表单数据解析——看它在路径里还是在查询串里。
  2. 检查编码端用的是哪一个:产出 %20 的是 RFC 3986 系,产出加号的是表单编码系。
  3. 再检查解码端:把加号当空格的(表单解析)和把加号当字面加号的(URI 解析)必须与编码端配成一对。
  4. 排查参数值里的加号是否被吞:需要传字面加号时一律写 %2B。
  5. 中文出问题时,先看编码是不是 UTF-8,再看有没有被二次编码(%25 开头往往说明被编了两遍)。

相关疑问

加号在路径里也会被当作空格吗?

不会。路径只按 URI 规范解析,加号就是字面加号,只有查询串按表单格式解析时它才代表空格,所以路径里的空格必须写成 %20。

为什么有的网站用加号,有的用 %20?

看它的参数是怎么产生的:HTML 表单提交或 URLSearchParams 生成的会带加号,而代码里用 encodeURIComponent 拼出来的通常是 %20,两者都能正常工作,前提是解析端与编码端匹配。

%25 开头的编码是什么意思?

多半是二次编码。百分号本身被编码成 %25,说明这段数据被编了两遍,解一次就还原成 %,再解一次才是原文,处理时注意不要漏解或多解。

把空格统一换成 %20 会有副作用吗?

正常不会有。%20 在所有上下文里都表示空格,是通用做法;唯一要注意的是别把「本来就该保留的加号」一并改写掉。

内容标识:本页内容由人工智能辅助生成,并经人工核对与编辑。详见 人工智能生成内容标识说明。
内容说明:本页针对具体使用问题作答,方法步骤与数值由本站自行整理与复算,事实性内容以对应官方规范与文档为准。内容最后核对日期:2026-10-09。若发现错误,欢迎通过页脚反馈入口告知。