Base64 文本编码 / 解码(中文与 emoji 不乱码 · URL-safe 输出)

把文字转成 Base64 或还原回来,全程按 UTF-8 字节走,中文、emoji 都不会报错。支持 URL-safe(- _)与去掉 = 填充,顺带给出字节数和膨胀率。输入的内容不会离开这台设备。

四组编码好的对照

打进去直接编码出来勾上 URL-safe填充也去掉
HiSGk=SGk=SGk
a?>YT8+YT8-YT8-
hi?>aGk/Pg==aGk_Pg==aGk_Pg
🎉8J+OiQ==8J-OiQ==8J-OiQ
编码不是加密

Base64 是什么

Base64 按比特重排字节:每 3 个字节(24 bit) 切成 4 组 6 bit,按组去一张固定的 64 字符表里取下标(A-Z、a-z、0-9、+、/)。6 bit 恰好是一个可打印 ASCII 字符,这就是用纯文本搬运字节的原理。末尾不满 3 字节用 = 补到 4 的倍数:差 1 字节写 ==,差 2 字节写 =。

它是编码,不是加密

字符表公开且固定,5L2g5aW9 谁都能一步还原成「你好」,没有任何密钥参与。别拿它存密码,也别拿它「混淆」敏感字段:配置里写 password: MTIzNDU2 和明文没有实质区别。要保密请上真正的加密(比如 AES-GCM),Base64 只配当密文外壳。

中文和 emoji 为什么会踩坑

btoa / atob 收发的是 Latin-1:每个码点必须不大于 0xFF。「你」是 U+4F60,emoji 是两个代理项,btoa("你好") 直接抛 InvalidCharacterError。必须先把字符串变成 UTF-8 字节,再在字节上做 Base64——靠 TextEncoder / TextDecoder 配一张手写字符表就够了。解码走 fatal: true,贴进来的是图片、zip 这类真二进制时会明确报错,而不是给你一串 U+FFFD。

URL-safe 变体、填充与体积

/ 是路径分隔符、+ 在查询串里代表空格,所以 JWT、query 参数、文件名都用 RFC 4648 §5 的 base64url:+ → -、/ → _,通常连 = 一起省掉——= 在查询串里还得二次转义,而按长度就能推出缺几位。填充默认保留,勾掉即得 JWT 形态;解码时两种字符表都认。

代价是体积:3 字节换 4 字符,膨胀率 33.3%,短文本更亏(1 个字节要写 2 个字符)。100 KB 的图片内联成 data:image/png;base64, 就是 133 KB,还挤占 HTML、丢掉独立缓存。

常见问题

长度不是 4 的倍数也能解吗? 能。解码跟 atob 的宽容规则一致:先去掉换行与空格,模 4 余 2 或 3 视作省略了填充,自动补齐并在提示里说明;余 1 数学上不可能,直接报错而不是猜。写了 = 但数量对不上也报错。

解出来是乱码? 多半原文不是 UTF-8——GBK 老文本,或本来就是二进制。这里会报错而不是硬拼假汉字;先确认对方编码。

我贴进来的内容去了哪? 进了那个循环,又原样出来。字符表写死在浏览器端的脚本里,没有 eval;你贴进来的东西不会出现在任何一次请求里,输入的内容不会离开这台设备。

微信
微信
支付宝
支付宝