现象:中文变成 %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 编解码工具:
- 把带
%XX的字符串粘进输入框; - 选择"解码",立刻得到可读中文;
- 反过来,选"编码"可以把中文转成合法 URL;
- 全程本地处理,不上传。
什么时候不用编码(或要注意)
- 路径 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 编解码工具:
- 把带
%XX的字符串粘进输入框; - 选择"解码",立刻得到可读中文;
- 反过来,选"编码"可以把中文转成合法 URL;
- 全程本地处理,不上传。
如果要分析的是完整 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 解码。访问 首页 查看更多开发者工具。
相关工具
相关文章
字符编码乱码排错手册:中文乱码、URL 编码、Base64 一次讲清
中文变问号、锟斤拷、%E4%B8%AD 看不懂?本手册按症状速查,覆盖乱码成因、URL 百分号编码、Base64 中文问题、Unicode 转义四类高频场景,附编码基础速查与排查流程。
Base64 解码后中文变成乱码 / 问号(�)怎么办?
Base64 解码后中文变成乱码或黑色问号方块怎么办?讲清"编码的是字节不是字符"这一根因,并给出命令行、代码和在线工具三种正确解法,全程本地处理。
如何批量把多个文件或文本转成 Base64(不走脚本也能做)
需要把几十张图片或一堆字符串一次性转成 Base64?本文讲解批量 Base64 编码的方法,并一步步用本地批量工具处理,避免写脚本、避免文件上传泄露。