Полезный код Base64 начинается с определения того, что на самом деле является входными данными. Для строки JavaScript требуется кодировка символов; в файле уже есть байты; Значение JSON сначала требует сериализации. Сохранение этих шагов видимыми упрощает отладку и предотвращает случайное двойное кодирование.
Закодируйте небольшое значение JSON.
Сериализуйте значение ровно один раз, закодируйте эту строку как UTF-8, затем закодируйте байты как Base64. Этот пример включает поле, отличное от ASCII, для отслеживания реализаций, которые работают только с английским языком. Он предназначен для небольших полезных нагрузок; временная строка байтов увеличивает использование памяти.
const value = { message: '你好', count: 3 };
const text = JSON.stringify(value);
let binary = '';
for (const byte of new TextEncoder().encode(text)) {
binary += String.fromCharCode(byte);
}
const encoded = btoa(binary);
const bytes = Uint8Array.from(atob(encoded), c => c.charCodeAt(0));
const json = new TextDecoder('utf-8', { fatal: true }).decode(bytes);
console.log(JSON.parse(json).message); // 你好
Успешное декодирование Base64 не гарантирует корректность JSON. Обработайте декодирование UTF-8 и JSON.parse как отдельные точки отказа. Если декодированное содержимое уже представляет собой строку, содержащую JSON, при его повторной сериализации добавляются кавычки и экранируются; это меняет полезную нагрузку.
Прочитать выбранный файл в байтах
Для браузера File, используйте arrayBuffer() когда вам нужны базовые байты. Не используйте file.text() для изображения, архива или зашифрованного файла: недопустимые последовательности символов могут стать символами замены. Если пункту назначения необходимы данные URI, FileReader.readAsDataURL() предоставляет оболочку, а также данные Base64.
// file is a File selected by the user.
const bytes = new Uint8Array(await file.arrayBuffer());
console.log(bytes.byteLength); // original file size in bytes
// Pass bytes to a byte-oriented encoder, not TextEncoder.
Проверки туда и обратно, которые выявляют реальные ошибки
Сравните декодированные байты с исходным массивом байтов. Сравнение снимков экрана или имен файлов не позволяет обнаружить измененный байт. Включите пустой ввод, все значения байтов от 0 до 255, текст на китайском языке, смайлы и полезную нагрузку, длина которой оставляет один или два байта в последней группе. Для пакета файлов сохраняйте имя, размер и результат каждого файла независимо, чтобы одна ошибка не могла перезаписать другой успешный результат.
Сохраняйте преобразования локальными, если ваш рабочий процесс намеренно не вызывает API. Сетевой запрос, содержащий закодированные выходные данные, по-прежнему отправляет базовые данные в обратимой форме. Информацию о поведении байтовой строки и ограничениях функции браузера в Юникоде см. МДН: btoa().