Decodex

DECODEX · BASE64 · UTF-8

JavaScript中文Base64转换:解决btoa的Unicode错误

使用TextEncoder、atob和TextDecoder转换中文、韩文和表情符号。提供经过验证的UTF-8代码与示例。

btoa()接收码元在单字节范围内的二进制字符串,不会自动转换为UTF-8。中文、韩文、印地语和许多表情符号可能导致InvalidCharacterError。请显式转换为UTF-8字节。

编码及解码Unicode

TextEncoder将文本转换为字节。下方代码在调用btoa前分块处理,避免大文本触发函数参数数量限制。恢复文本时,把atob的字节值交给TextDecoder按UTF-8读取。fatal选项会检测无效字节并报错。

检查往返转换

안녕하세요 😀编码为7JWI64WV7ZWY7IS47JqUIPCfmIA=。解码必须还原相同文本、空格和表情符号。示例链接只使用预设公开示例名称,不把用户文本放入URL。Decodex在浏览器内处理最多5 MB的UTF-8文本。

区分错误发生的阶段

atob错误通常与Base64字符、填充或前缀有关。TextDecoder错误可能表示二进制数据或其他字符编码,即使Base64字符集有效。Node.js中可用Buffer.from(text, "utf8").toString("base64"),但宽松的解码不能代替输入验证。

转换此示例

// Browser JavaScript: text → UTF-8 bytes → Base64.
function utf8ToBase64(text) {
  const bytes = new TextEncoder().encode(text);
  let binary = '';
  for (let i = 0; i < bytes.length; i += 8192) {
    binary += String.fromCharCode(...bytes.subarray(i, i + 8192));
  }
  return btoa(binary);
}

// Accept standard Base64 or Base64URL, with complete or omitted padding.
function base64ToUtf8(value) {
  let normalized = value.replace(/\s/g, '').replace(/-/g, '+').replace(/_/g, '/');
  if (!/^[A-Za-z0-9+/]*={0,2}$/.test(normalized) ||
      normalized.length % 4 === 1 ||
      (normalized.includes('=') && normalized.length % 4 !== 0)) {
    throw new Error('Invalid Base64 characters, length or padding');
  }
  normalized += '='.repeat((4 - normalized.length % 4) % 4);
  const binary = atob(normalized);
  const bytes = Uint8Array.from(binary, character => character.charCodeAt(0));
  return new TextDecoder('utf-8', { fatal: true }).decode(bytes);
}

const text = '안녕하세요 😀';
const encoded = utf8ToBase64(text);
console.log(encoded); // 7JWI64WV7ZWY7IS47JqUIPCfmIA=
console.log(base64ToUtf8(encoded)); // 안녕하세요 😀

转换此示例 →

Base64 → UTF-8 · UTF-8 → Base64

常见问题

atob能直接返回可读中文吗?

不能。它返回二进制字符串。把值转换为Uint8Array,再用TextDecoder("utf-8")读取。建议采用明确的字节转换,避免依赖旧的unescape()。

参考资料

更多Base64指南