TIP

URL编码中文乱码怎么办?一文搞懂百分号编码原理

2026.03.19 · 阅读 8 分钟

做前端或后端开发时,你一定遇到过这种情况:在 URL 里拼了一段中文参数,结果跳转后变成了一堆 %E4%BD%A0%E5%A5%BD 的天书。或者反过来,从地址栏复制一段 URL 发给别人,对方打开却乱码了。又或者 API 联调时,后端收到的中文参数全是问号。

这些问题的根源都是 URL 编码(Percent-encoding / 百分号编码)。搞懂原理,乱码问题就能系统性地解决了。

为什么 URL 里不能直接写中文

URL 标准(RFC 3986)规定,URL 里只能包含 ASCII 字符的一个子集:英文字母、数字、以及少量特殊符号(- _ . ~ : / ? # [ ] @ ! $ & ' ( ) * + , ; =)。其他所有字符——中文、日文、空格、emoji——都必须经过编码才能出现在 URL 中。

编码规则:把字符转成 UTF-8 字节序列,每个字节用 %XX(两位十六进制数)表示。

URL 编码示例
原文: 你好
UTF-8字节: E4 BD A0 | E5 A5 BD (每个汉字3字节)
URL编码: %E4%BD%A0%E5%A5%BD
原文: hello world
URL编码: hello%20world (空格 = %20)

encodeURI vs encodeURIComponent:最常搞混的两个函数

JavaScript 提供了两个 URL 编码函数,名字差不多但行为完全不同。用错了就是 bug 的来源:

两个编码函数对比
函数 编码范围 保留字符 适用场景
encodeURI中文等非 ASCII: / ? & = # @ + ,编码整个 URL
encodeURIComponent所有特殊字符- _ . ~ ! * ' ( )编码参数值
用错函数的后果
// ✓ 正确:参数值用 encodeURIComponent
url = '/search?q=' + encodeURIComponent('价格>100&类型=A')
// → /search?q=%E4%BB%B7%E6%A0%BC%3E100%26%E7%B1%BB%E5%9E%8B%3DA
// ✗ 错误:参数值用 encodeURI → & 没编码,参数被截断
url = '/search?q=' + encodeURI('价格>100&类型=A')
// → /search?q=%E4%BB%B7%E6%A0%BC>100&%E7%B1%BB%E5%9E%8B=A ← 变成两个参数了!
记忆口诀:编码整个 URL 用 encodeURI(保留 URL 结构字符),编码参数值用 encodeURIComponent(什么都编码)。90% 的场景你需要的是 encodeURIComponent。

五个常见乱码场景及解决方案

◆ 场景一:后端收到的中文参数是乱码

原因:前端拼接 URL 时参数值包含 &=,但只用了 encodeURI,导致参数被截断。
解决:参数值一律用 encodeURIComponent 编码。

◆ 场景二:复制的 URL 发给别人打不开

原因:浏览器地址栏会"美化"显示中文,但实际复制出来的可能是部分编码或未编码的混合体。
解决:复制 URL 前右键 → 复制链接地址(而不是从地址栏手动选中复制),或者用纳米工房的 URL 编解码工具处理后再发送。

◆ 场景三:API 返回 %XX 编码,想看原文

解决:用 decodeURIComponent 解码。如果报 "URI malformed" 错误,说明编码不完整(比如 %E4%BD 缺了最后一个字节)或者不是 UTF-8 编码。

◆ 场景四:双重编码(%25E4...)

原因:已经编码过的字符串被再次编码——% 本身被编成 %25,于是 %E4 变成 %25E4
解决:检查代码中是否有两处地方都做了编码。只编码一次。

◆ 场景五:+ 号被当成空格

原因:在 application/x-www-form-urlencoded 格式中,空格编码为 +。如果参数值本身包含 +(比如 "C++"),就会被解码成空格。
解决:用 encodeURIComponent 编码 + 会变成 %2B,不会和空格冲突。

不同语言的编码函数对照

各语言 URL 编解码函数
语言 编码函数 解码函数
JavaScriptencodeURIComponent()decodeURIComponent()
Pythonurllib.parse.quote()urllib.parse.unquote()
PHPurlencode() / rawurlencode()urldecode()
JavaURLEncoder.encode(s, "UTF-8")URLDecoder.decode()
Gourl.QueryEscape()url.QueryUnescape()
PHP 的 urlencode() 把空格编码成 +,rawurlencode() 编码成 %20。和 JavaScript 的 encodeURIComponent 行为一致的是 rawurlencode()。

在线编解码工具

打开纳米工房URL 编解码工具
粘贴需要编码或解码的文本
选择模式(encodeURIComponent / encodeURI / Base64),结果实时显示

工具会自动检测输入内容是否已编码——检测到 %XX 格式会自动解码显示原文。也支持 URL 解析模式,把完整 URL 拆解成协议、域名、路径、查询参数各个部分,方便排查编码问题。

常见问题

emoji 怎么编码?

emoji 和中文一样走 UTF-8 编码,但 emoji 通常是 4 字节字符,所以编码后更长。比如 😀 编码为 %F0%9F%98%80

URL 有长度限制吗?

HTTP 标准没有规定上限,但实际限制来自浏览器和服务器:Chrome 约 2MB,IE 约 2083 字符,Nginx 默认 8KB。如果 URL 编码后超长,考虑改用 POST 请求把数据放 body 里。

为什么有时候看到 %u 开头的编码?

%uXXXX 是非标准的 Unicode 编码格式(JavaScript 的 escape() 函数输出),不是合法的 URL 编码。现代开发中不要使用 escape(),它已经被废弃了。

ESC