Decodex

DECODEX · BASE64 · UTF-8

Base64 в JavaScript: Unicode и ошибка btoa

Кодирование русского текста, корейского и эмодзи через TextEncoder, btoa, atob и TextDecoder без потери UTF-8.

btoa() принимает двоичную строку, каждая единица которой помещается в байт. Он не преобразует текст в UTF-8 автоматически. Многие символы Unicode вызывают InvalidCharacterError: сначала получите байты UTF-8.

Кодирование и декодирование UTF-8

TextEncoder создаёт байты текста. Код ниже обрабатывает их блоками перед btoa, избегая ограничения числа аргументов функции. При декодировании преобразуйте результат atob в Uint8Array и используйте TextDecoder. Параметр fatal обнаруживает некорректные байты UTF-8.

Проверка полного преобразования

안녕하세요 😀 кодируется как 7JWI64WV7ZWY7IS47JqUIPCfmIA=. Декодирование должно вернуть тот же текст и пробелы. Ссылка использует фиксированное имя публичного примера, не помещая ваш текст в URL. Decodex обрабатывает до 5 MB текста UTF-8 в браузере.

Определите этап ошибки

Ошибка atob обычно связана с алфавитом, заполнением или префиксом. Ошибка TextDecoder может указывать на двоичные данные либо другую кодировку. В 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 сразу читаемый Unicode?

Нет. Он возвращает двоичную строку. Преобразуйте значения в Uint8Array и прочитайте их через TextDecoder("utf-8"). Не полагайтесь на старые решения с unescape().

Источники

Другие руководства Base64