怎么用
- 选择「编码」或「解码」。
- 编码时,先选好这段文字的用途。要放进 = 和 & 之间、或者两个斜杠之间的内容,选「参数值或路径中的一段」,绝大多数情况都该选它。只有手上是一整条带中文或空格的网址、又要保留其中的斜杠和问号时,才选「整条网址」。想得到和网页表单提交一模一样的结果,选「表单数据」。
- 输入或粘贴文字,结果会随输入实时更新,点「复制」即可取走。
- 解码时,粘贴编码后的内容或整条链接。如果内容来自表单提交或者搜索页的网址,勾选「把 + 当作空格」。如果里面有不属于转义的孤立 %,勾选「保留无效的 %」,不必手动去改。
- 只要输入的是一条完整网址,下方「这条网址的组成」会逐行列出协议、主机、端口、路径、锚点,以及每一个查询参数解码后的值。
百分号编码的原理
网址里只允许出现有限的一组 ASCII 字符,而且其中不少身兼职责:/ 分隔路径,? 开始查询部分,& 和 = 分隔参数,# 开始锚点。RFC 3986 规定了放入其他字符的办法:先把文字转成 UTF-8 字节,再把每个字节写成 % 加两位十六进制数。空格变成 %20;一个汉字在 UTF-8 里占 3 个字节,就变成 3 个转义,比如「你」是 %E4%BD%A0。所以常见的「网址里一串 %E4%B8%AD」,其实就是被编码了的中文。
为什么有三种模式
区别在于哪些字符保持原样。encodeURIComponent 除了字母、数字和 - _ . ! ~ * ' ( ) 之外全部编码,所以值里就算有 & 或 /,也不会破坏它所在的网址。encodeURI 则额外保留 ; , / ? : @ & = + $ # 这些结构字符,因为它假定你给的是一整条网址。把 encodeURI 用在单个参数值上是很常见的错误:值「a&b」编码后还是「a&b」,服务器会把它读成两个参数。
表单编码(application/x-www-form-urlencoded,定义在 WHATWG URL 标准 中)是浏览器提交网页表单时使用的格式,也是 URLSearchParams 生成的格式。它把空格写成 +,并且连 ! ' ( ) ~ 也一起编码。这就是搜索页网址里常见 q=hello+world 的原因,也是表单数据里真正的加号必须写成 %2B 的原因。
精确地解码
JavaScript 自带的 decodeURIComponent 遇到坏数据只会抛出一句「URI malformed」,不说错在哪里。这个工具自己逐个处理转义:把连续的 %XX 收集成字节,再按严格的 UTF-8 校验。这样它能分清两种错误:一种是 % 后面没有跟两位十六进制数,另一种是某个多字节字符被截断了。后者通常是网址被人从一个汉字的中间剪断造成的。
中文域名
域名部分不用百分号编码,而是按 RFC 3492 转成以 xn-- 开头的 Punycode。拆解面板会同时显示两种形式,让你看出「例子.com」和「xn--fsqu00a.com」其实是同一个主机。
算例
| 输入 | 模式 | 结果 |
|---|---|---|
你好 | 参数值 | %E4%BD%A0%E5%A5%BD |
a b&c=d/é | 参数值 | a%20b%26c%3Dd%2F%C3%A9 |
https://example.com/a b?q=1&r=é#x | 整条网址 | https://example.com/a%20b?q=1&r=%C3%A9#x |
a b+c | 表单数据 | a+b%2Bc |
it's (fine)!*~ | 表单数据 | it%27s+%28fine%29%21*%7E |
😀 | 参数值 | %F0%9F%98%80 |
「你好」两个汉字共 6 个字节,编码后变成 18 个字符。解码 %E4%BD 会报错,因为它只是一个三字节汉字的前两个字节,最常见于网址被截断。解码 100%zz 会指出第 4 个字符,也就是那个后面没有跟十六进制数的 %;如果勾选了「保留无效的 %」,像 100% 结尾这样孤立的 % 会原样保留。
解码 %25E4%25BD%25A0 一次,得到的是 %E4%BD%A0,再解码一次才是「你」。出现 %25 往往就说明这个值被编码了两次。
粘贴 https://user@例子.com:8443/路径/a%20b?q=%E4%BD%A0&q=2&empty=&flag#frag,拆解结果是:主机「例子.com(xn--fsqu00a.com)」,端口 8443,路径「/路径/a b」,以及 4 个参数:q = 你、q = 2、empty 为空、flag 为空。重复的参数名和空值都会保留,因为不同的服务器对它们的处理方式不同。
常见错误
- 重复编码。 参数值编码一次后,放进网址又整体编码了一次,%20 就变成了 %2520。每个值只在拼进网址的那一刻编码一次。
- 把整条网址当成参数值编码。 encodeURIComponent 会把 https:// 变成 https%3A%2F%2F。当这条网址本身就是某个参数的值时(比如登录后的跳转地址),这样做是对的;其他情况下就是错的。
- 在所有地方都把 + 当空格。 只有表单数据用 + 表示空格;在路径里,+ 就是一个普通的加号。
局限
- 只支持 UTF-8。 一些老网站曾用 GBK 编码中文,比如「中」写成 %D6%D0。这样的字节不是有效的 UTF-8,会被报告为错误;勾选宽松选项后,它们会以转义的形式原样保留。
- 一次只解一层。 值被编码了两次时,点「用结果作为输入」再解码一次。
- 拆解面板使用 WHATWG 网址解析规则, 和浏览器相同。没有写协议的内容会按 https:// 来展示,含有空格的内容不被视为网址。
常见问题
网址里的 %E4%BD%A0 是什么?
是被百分号编码的中文。每个汉字在 UTF-8 里占 3 个字节,每个字节写成一个 %XX,%E4%BD%A0 就是「你」。粘贴到解码框里即可还原。
encodeURI 和 encodeURIComponent 有什么区别?
encodeURIComponent 会编码 / ? & = 这些在网址里有特殊含义的字符,适合单个参数值;encodeURI 保留它们,只适合整条网址。
空格应该编码成 %20 还是 +?
路径和大多数接口里用 %20;网页表单和很多搜索页网址里用 +。
为什么网址里出现了 %2520?
它被编码了两次:% 本身又被编成了 %25。解码两次即可还原,同时应该修改代码,只编码一次。
内容会被上传吗?
不会。编码、解码和网址拆解都在你的浏览器里完成。