链接里的中文为什么变成了 %E4%B8%AD 这种东西?
那是 URL 编码后的中文,不是乱码。URL 规范只允许英文字母、数字和少数符号,中文得先按 UTF-8 转成字节、每个字节写成一个 %XX。一个汉字通常占三个 %XX。把整段粘到上面点「解码」就能还原。反过来,你在浏览器地址栏看到的中文链接,其实也是浏览器帮你把编码后的形式显示成了中文,复制出来往往还是 %XX。
%E4%B8%AD%E6%96%87 这类百分号编码可以在这里还原成中文;反过来也行,把中文、空格、特殊字符编成能安全放进 URL 的形式。支持 UTF-8 和 GBK 两种字符集,能识别加号形式的空格,粘进一整条链接还会自动拆开查询参数逐个解码。全部在浏览器本地完成,不上传任何数据。%XX 就自动切到解码,不带就切到编码,手动点过按钮之后不再自动切。% 片段不会整段失败,会原样保留那几个字符,其余照常解出来。URL 的规范(RFC 3986)只允许出现英文字母、数字和少数几个符号,中文、空格、引号这些字符都不在允许之列。要把它们放进链接,就得先按某种字符集转成字节,再把每个字节写成一个百分号加两位十六进制数——这就是百分号编码,也叫 URL 编码。「中」在 UTF-8 下是三个字节 E4 B8 AD,写出来就是 %E4%B8%AD。所以看到一串 %E4%B8... 不是乱码也不是加密,只是同一段文字的另一种写法,三个 %XX 一组基本就能判断是 UTF-8 编的中文。
这是写代码时最容易搞错的一处。encodeURIComponent 会把 : / ? # & = 这些结构字符也编掉,适合编单个参数值;encodeURI 会保留它们,适合编整条已经拼好的链接。用错的后果很具体:把整条 URL 交给 encodeURIComponent,https:// 会变成 https%3A%2F%2F,链接直接失效;反过来用 encodeURI 编一个本身就含 & 的参数值(比如搜索词是「A&B」),那个 & 会被原样保留,服务端就会把它当成参数分隔符,参数被截断成两个。上面的编码模式两种都提供,默认是编参数值那种。
URL 编码和 Base64一样,是编码不是加密:规则完全公开,没有密钥,任何人拿到都能一步还原,本页就是。它存在的意义是让特殊字符能安全穿过 URL 这条通道,不提供任何保密性。所以把订单号、手机号、内部 ID 做一次 URL 编码就放进链接,等于没做任何处理——浏览器地址栏、服务器日志、Referer 头里躺着的都是明文。要不可逆请看 SHA-256,要传敏感参数请走 POST 并上 HTTPS。顺带一提,「URL 解密」这个说法本身就不成立,准确的词是解码。
空格有两种写法。表单提交用的 application/x-www-form-urlencoded 把空格编成 +,而路径和现代 API 普遍用 %20。麻烦的是 JS 的 decodeURIComponent 不认 +,会原样留下一个加号,所以本页给了开关,默认按空格解。反过来,如果内容里本来就有加号(比如1+1),编码时它会变成 %2B,这是对的。
字符集是另一个坑。现在默认都是 UTF-8,但不少老站点、老系统用的是 GBK,「中」在 GBK 下是两个字节 %D6%D0。用 UTF-8 去解 GBK 编的内容,得到的就是问号或方块。本页解码侧可以切 GBK;编码侧只做 UTF-8,因为浏览器原生只能编 UTF-8。
各语言的函数名对照。PHP 的 urlencode 会把空格编成 +、rawurlencode 编成 %20,对应的解码是 urldecode / rawurldecode;Java 的 URLEncoder.encode(s, "UTF-8") 走的是表单那套,也是 +;Python 用 urllib.parse.quote / unquote,其中 quote_plus 才编成 +;JavaScript 只有 encodeURIComponent / decodeURIComponent,永远是 %20。前后端对不上时,八成就是差在这个加号上。
那是 URL 编码后的中文,不是乱码。URL 规范只允许英文字母、数字和少数符号,中文得先按 UTF-8 转成字节、每个字节写成一个 %XX。一个汉字通常占三个 %XX。把整段粘到上面点「解码」就能还原。反过来,你在浏览器地址栏看到的中文链接,其实也是浏览器帮你把编码后的形式显示成了中文,复制出来往往还是 %XX。
切到 GBK 再解一次。默认按 UTF-8 解,而不少老站点和老系统用的是 GBK,同一个「中」字在 UTF-8 下是 %E4%B8%AD、在 GBK 下是 %D6%D0,用错字符集必然出问号或方块。一个简单的判断方法:%XX 三个一组多半是 UTF-8,两个一组且首字节在 %A1–%FE 之间多半是 GBK。
前者连 : / ? # & = 一起编掉,用来编单个参数值;后者保留这些结构字符,用来编整条链接。拼 URL 时几乎总该用 encodeURIComponent 去编每个参数值,再自己拼上 ? 和 &。用 encodeURI 编整条 URL 只适合「链接已经拼好、只想让里面的中文和空格合法化」这一种场景。
要看上下文,这也是最容易出错的地方。表单提交(application/x-www-form-urlencoded)把空格编成 +,所以查询字符串里的 + 通常就是空格;而路径部分和现代 API 里的 + 一般就是加号本身。JS 的 decodeURIComponent 不做这个转换。本页默认把 + 当空格,如果你的内容里本来就有加号(比如 C++),把那个勾去掉再解。
说明字符串里有不合法的百分号片段——% 后面不是两位十六进制数,或者字节序列拼不成合法的 UTF-8。常见于复制时漏了字符,或者内容被编码了两次(%25E4 这种,%25 就是 % 本身,再解一次才是中文)。本页不会因为这个整段失败:不合法的片段原样保留,其余照常解出来,你能直接看出是哪一段有问题。
不能,它和加密没有关系。编码规则是公开的,任何人都能一步还原,你的手机号、订单号编完之后仍然是明文躺在地址栏、浏览器历史、服务器日志和 Referer 头里。真要保护敏感参数,用 POST 提交、走 HTTPS、在服务端做权限校验,或者改成不可逆的哈希值。「URL 解密」这个说法本身就不准确,正确的叫法是解码。
不会。编解码用的是浏览器内置的 encodeURIComponent / TextDecoder,全部在你的设备上算完直接显示,没有一个字节离开浏览器。页面加载完之后断开网络,这个工具照常可用——这是最直接的验证方法。带 token、带订单号的链接可以放心粘。详见隐私政策。
有。JSON 格式化把接口返回展开成能读的层级,Base64 编解码处理另一种常见编码,时间戳转换把日志里的 10 位/13 位数字换成人能读的时间,MD5 和 SHA-256 算校验用的哈希。全部同样在本地运行,不上传数据。