传参要编码中文总乱码?写了个 Base64 编解码工具,浏览器里直接转
接口传参、配置文件塞令牌,经常要把一段文本编码成 Base64。在线工具要么要登录、要么把内容传到别人服务器,敏感字符串谁敢往上贴。浏览器自带 btoa/atob 又坑——直接塞中文就报错。我写了个纯前端 Base64 编解码工具,UTF-8 中文也能稳转,数据不出本机。
一、btoa 为什么怕中文
btoa 设计之初只认 Latin1(0–255)字符,中文的 Unicode 码点远超这个范围,直接丢进去就抛 InvalidCharacterError。所以编码前得先把字符串转成 UTF-8 字节序列,再交给 btoa。
二、编码:先 UTF-8 再 btoa
最省事也最稳的一招是用 encodeURIComponent 把中文变成 %xx 形式,再 unescape 展开成字节:
function b64encode(str) {
return btoa(unescape(encodeURIComponent(str)));
}
function b64decode(b64) {
return decodeURIComponent(escape(atob(b64)));
}
encodeURIComponent('中') 得到 %E4%B8%AD,unescape 把它还原成三个 Latin1 字符,btoa 就能处理了。解码是严格逆过程。这套写法在所有现代浏览器都稳,escape/unescape 虽被标 deprecated,但编解码场景里它比手写字节转换省心太多。
如果介意 deprecated,也可以用 TextEncoder 走标准路线:
function b64encodeU8(str) {
const bytes = new TextEncoder().encode(str);
let bin = '';
bytes.forEach(b => bin += String.fromCharCode(b));
return btoa(bin);
}
三、解码也要兜底
atob 遇到非法 Base64 字符(比如多了空格、换行)会抛错,包一层 try/catch 体验好很多:
function safeDecode(b64) {
try {
return decodeURIComponent(escape(atob(b64.trim())));
} catch (e) {
return '解码失败:不是合法的 Base64';
}
}
.trim() 顺手清掉复制时带上的首尾空格,少一个让人抓狂的报错来源。
编码前后对照
以"华为云博客"为例:
| 阶段 | 内容 |
|---|---|
| 原文 | 华为云博客 |
| UTF-8 字节 | E5 8D 8E E4 BA 91 E4 BA 91 E5 8D 9A E5 AE A2 |
| Base64 | 5Y2O5Y2O5LqR5Y2O5LqR |
中文越长,Base64 越膨胀(约 1.37 倍),不适合拿来存大段文本,当传参或令牌载体刚好。
几个容易踩的点
- 中文必须走 UTF-8 中转:直接
btoa('中')必报错,这是新手最高频的坑,记住先encodeURIComponent。 - URL 安全的 Base64:标准 Base64 含
+ / =,放 URL 里会被转义。需要时用- _替换+ /并去掉=,即"URL-safe Base64"。 - 解码失败别崩页:非法输入
try/catch兜住,返回可读提示,比白屏强。 - 不是加密:Base64 只是编码,谁都能解,令牌、密码千万别当它加密用,该 HTTPS 走 HTTPS。
小结
Base64 编解码工具核心就是 btoa/atob,真正的坑只有中文——必须先经 UTF-8 中转(encodeURIComponent+unescape 或 TextEncoder)再交给 btoa。解码用 try/catch 兜底非法输入,顺手 .trim() 清掉多余空白。记住它只是编码不是加密,敏感内容别依赖它保密。浏览器原生能力够用,不联网也能转,调试接口时随手就开。
- 点赞
- 收藏
- 关注作者
评论(0)