Skip to content
编码转换2026-08-284 分钟阅读

现象:中文变成 %XX 一串

你把 https://example.com/搜索?q=中文 复制到某处,中文变成了 https://example.com/%E6%90%9C%E7%B4%A2?q=%E4%B8%AD%E6%96%87。先放心:这是完全正常的,不是乱码。

为什么中文必须编码成 %XX

URL 的规范(RFC 3986)只允许一小部分** ASCII 字符直接出现在地址里(字母、数字和少数符号)。中文、空格、emoji 都不在白名单。为了把任意字符塞进 URL,就发明了百分号编码(Percent-encoding / URL Encoding)**:

  • 把字符先转成 UTF-8 字节;
  • 每个字节写成 % + 两位十六进制。

所以"中"的 UTF-8 是三个字节 E4 B8 AD,编码后就变成 %E4%B8%AD

| 原始 | UTF-8 字节 | 编码结果 | |---|---|---| | | E4 B8 AD | %E4%B8%AD | | 空格 | 20 | %20(或 +) | | A | 41 | A(无需编码) |

怎么解码回来

反向操作即可:把 %XX 按字节还原成 UTF-8。打开 ToolVault 工具匣 的 URL 编解码工具

  1. 把带 %XX 的字符串粘进输入框;
  2. 选择"解码",立刻得到可读中文;
  3. 反过来,选"编码"可以把中文转成合法 URL;
  4. 全程本地处理,不上传。

什么时候不用编码(或要注意)

  • 路径 vs 查询/搜索?q=搜索 都可以编码,但编码后都安全;不编码在某些服务器上会被拒绝。
  • + 的歧义:在查询串里 + 常被当成空格,所以空格更推荐编码成 %20 而非 +,避免歧义。更准确地说:application/x-www-form-urlencoded(HTML 表单)约定 + 是空格,而 RFC 3986 里 + 就是加号本身——同一个字符两种语义,跨系统传参时最容易踩坑。稳妥做法是自己编码时永远用 %20,解码时两种都接受。
  • 保留字符? & = / # 在 URL 里有语法意义,除非你想表达它们本身,否则该编码时要编码。典型 bug:把用户输入直接拼进 ?redirect= 参数,输入里带 & 就把后面的参数截断了——正确做法是先 encodeURIComponent 再拼接。

前端怎么处理:encodeURI vs encodeURIComponent

这两个 API 的区别是高频面试题,实际开发也真的会选错:

| API | 编码范围 | 适用 | |---|---|---| | encodeURI | 保留 ://?&= 等结构字符 | 编码整条 URL | | encodeURIComponent | 连 & = / 也编码 | 编码参数值 |

// 对:整条 URL 用 encodeURI
encodeURI('https://a.com/搜索?q=中')   // https://a.com/%E6%90%9C%E7%B4%A2?q=%E4%B8%AD

// 对:参数值用 encodeURIComponent
const q = 'a&b=c';
`https://a.com/search?q=${encodeURIComponent(q)}`
// https://a.com/search?q=a%26b%3Dc

// 错:encodeURIComponent 用于整条 URL,会把 :// 也编码掉
encodeURIComponent('https://a.com')   // https%3A%2F%2Fa.com

解码用对应的 decodeURI / decodeURIComponent。注意 decodeURIComponent 遇到孤立的 %(如字面量 100% 被误编码过一次)会直接抛 URIError,生产代码里要 try/catch。

还有一个隐藏坑:双重编码。编码两次后 %E4 变成 %25E4,解码一次得到的还是带 % 的串。判断方法是看解码结果里是否还有 %XX 残留——有就再解一次,但要设上限防止无限解。

怎么解码回来

反向操作即可:把 %XX 按字节还原成 UTF-8。打开 ToolVault 工具匣 的 URL 编解码工具

  1. 把带 %XX 的字符串粘进输入框;
  2. 选择"解码",立刻得到可读中文;
  3. 反过来,选"编码"可以把中文转成合法 URL;
  4. 全程本地处理,不上传。

如果要分析的是完整 URL 的结构(协议、路径、各查询参数),用 URL 参数解析器 更直接——自动按 &= 拆分并逐个解码,不用手动处理整串。

FAQ

为什么有的网站中文直接显示,有的变成 %XX?

取决于浏览器/服务器是否帮你做了"显示层"的解码。底层传输时仍然编码,只是界面上还原给你看。两者是同一份数据的不同呈现。

编码后链接还能正常打开吗?

能。服务器收到 %E4%B8%AD 会自动解码回"中"再处理,对最终访问没有影响。但日志和监控里你会同时看到两种形态,做 URL 去重或统计时记得先统一解码再比较。

Base64 和 URL 编码是一回事吗?

不是。URL 编码是按字节百分号化,专用于 URI;Base64 是把任意数据变可打印文本(见 Base64 工具)。用途不同。顺带一提 base64url 变体:把标准 Base64 里的 +/ 换成 -_、去掉填充,就是 JWT 里用的那种"URL 安全 Base64"。

接口收到的中文是 %XX 形态,存库前要手动解码吗?

取决于你的框架。Express/Koa/Spring 等都会自动解码查询参数;但路径片段请求体是否解码因框架而异。判断办法:把收到的值打印出来,还带 %XX 就说明该环节没解——在自己的入口处统一 decodeURIComponent 一次,别在多个业务代码里重复解。


本文由 ToolVault 工具匣 提供。相关工具:URL 编解码Base64 编解码JWT 解码。访问 首页 查看更多开发者工具。


广告