URL 编码中的空格:%20 与 +(何时该用哪一个)
%20 是 RFC 3986 定义的空格字符标准 percent-encoding 编码,应当用于 URL 路径以及大多数场景。而 + 号仅在 application/x-www-form-urlencoded 格式中表示空格,这种格式用于 HTML 表单提交和部分查询字符串。
%20 是什么意思?
%20 是空格字符(ASCII 码 32,十六进制 0x20)的 percent-encoding 表示形式,由 RFC 3986 定义。它是在 URI 的任意部分表示空格的标准方式,包括路径段、查询字符串和片段标识符。
当你在 URL 中看到 %20 时,它的含义很简单,就是"这里有一个空格"。例如,https://example.com/my%20file.pdf 指向的是一个名为 "my file.pdf" 的资源。所有 Web 服务器、浏览器和 HTTP 库都能通用地识别 %20。
+ 在 URL 中是什么意思?
用 + 号表示空格,源自 application/x-www-form-urlencoded 这一内容类型,它是在 HTML 规范中为编码表单数据而定义的。当使用 GET 方法提交 HTML 表单时,浏览器会在生成的查询字符串中把空格编码为 +。
例如,如果你在搜索表单中输入 "hello world" 并提交,浏览器会生成类似 https://example.com/search?q=hello+world 的 URL。这里的 + 表示"空格",但仅仅是因为该查询字符串使用了 form-urlencoded 格式。
需要特别注意的是,在 application/x-www-form-urlencoded 格式之外,+ 并没有任何特殊含义。在类似 /files/my+file.pdf 这样的 URL 路径中,+ 就是一个字面意义上的加号,而不是空格。所引用的文件名字面上就叫 "my+file.pdf"。
关键区别
两者最根本的区别在于它们各自所属的规范。%20 由 RFC 3986(URI 规范)定义,在 URL 的任何位置都有效。而 + 表示空格这一约定,则由 HTML/WHATWG 规范针对表单数据定义,只有在被明确当作 form-urlencoded 数据处理的查询字符串中才有效。
%20在路径、查询字符串、片段以及所有 URI 场景中都有效+只在application/x-www-form-urlencoded查询字符串中才表示"空格"- 在 URL 路径中,
+是一个字面意义上的加号,而非空格 %20始终是安全的;+则依赖于上下文- 如果你要在表单数据中编码一个字面意义的
+,它会变成%2B
你应该用哪一个?
使用 %20 的场景包括:以编程方式构建 URL、构造 REST API 请求、编码路径段,或者任何你拿不准的时候。它是 URI 中空格的通用正确编码方式。
使用 + 仅限于你有意生成 application/x-www-form-urlencoded 数据的情况,例如构建模拟 HTML 表单提交的查询字符串,或者某个 API 明确要求使用这种格式时。
大多数现代 API 和框架在查询字符串中同时接受 %20 和 +。不过,使用 %20 的可移植性更好,也能避免歧义,尤其是当查询字符串可能被用在表单提交之外的场景时。
不同语言如何处理空格
不同的编程语言及其标准库,在编码空格时可能默认使用 %20 或 +。了解你所用语言的默认行为,有助于避免意外情况。
// JavaScript
encodeURIComponent('hello world'); // "hello%20world" (%20)
new URLSearchParams({q: 'hello world'}).toString(); // "q=hello+world" (+)
// 若要在查询字符串中强制使用 %20:
new URLSearchParams({q: 'hello world'}).toString().replace(/\+/g, '%20');
# Python
from urllib.parse import quote, quote_plus, urlencode
quote('hello world', safe='') # "hello%20world" (%20)
quote_plus('hello world') # "hello+world" (+)
urlencode({'q': 'hello world'}) # "q=hello+world"(默认使用 +)
# 若要强制使用 %20:
urlencode({'q': 'hello world'}, quote_via=quote) # "q=hello%20world"
// PHP
rawurlencode('hello world'); // "hello%20world" (%20)
urlencode('hello world'); // "hello+world" (+)
// rawurlencode 遵循 RFC 3986
// urlencode 遵循 application/x-www-form-urlencoded