Base64
Base64 (за основою 64) – це група споріднених кодувань перетворення з двійкової у текстову форму, що представляють двійкові дані у вигляді рядка ASCII за допомогою перетворення їх на представлення з системою числення 64. Термін Base64 походить від конкретного кодування передачі вмісту MIME.
Коли термін "Base64" вживається сам по собі на позначення певного алгоритму, він зазвичай означає версію Base64, описану у RFC 4648, розділі 4, яка використовує наступний алфавіт для представлення розрядних цифр системи числення 64, разом із =
як символом відступу:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
Поширена варіація – "безпечний для URL Base64", котрий пропускає відступ і замінює +/
на -_
, щоб уникнути символів, які можуть створювати проблеми у сегментах шляху URL і параметрах запиту. У цьому кодуванні немає потреби, якщо ви не кладете дані в сегмент шляху чи параметр запиту: наприклад, адреси URL даних не мають ані першого, ані другого, а отже можуть використовувати стандартне кодування Base64.
Схеми кодування Base64 заведено використовувати для кодування двійкових даних для зберігання чи передачі засобами, що можуть працювати лише з текстом ASCII (або певною надмножиною ASCII, що все одно не здатна приймати довільні двійкові дані). Це забезпечує, що дані залишаються незмінними під час транспортування. Поширені застосування Base64:
- Електронна пошта через MIME
- Зберігання складних даних у XML
- Кодування двійкових даних, щоб їх можна було включити в URL-адресу
data:
Збільшення розміру при кодуванні
Кожна цифра Base64 представляє 6 біт даних. Отже, три 8-бітові байти вихідного рядка чи двійкового файлу (3×8 біт = 24 біти) можна представити чотирма 6-бітовими цифрами Base64 (4×6 = 24 біти).
Це означає, що версія рядка чи файлу в Base64 зазвичай приблизно на третину більша за вихідні дані (точний приріст розміру залежить від різних факторів, таких як абсолютна довжина рядка, остача від ділення його довжини на 3 та те, чи використовуються символи відступу).
Підтримка в JavaScript
Для розкодування та кодування рядків Base64 браузери надають дві функції JavaScript:
Window.btoa()
(також доступна у воркерах) – створює рядок ASCII, закодований Base64, з рядка двійкових даних ("btoa" слід читати як "binary to ASCII", "двійкове в ASCII").Window.atob()
(також доступна у воркерах) – розкодовує рядок, закодований Base64 ("atob" слід читати як "ASCII to binary", "ASCII у двійкове").
[!NOTE] Base64 – це двійкове кодування, а не текстове, але
btoa
таatob
були додані до вебплатформи до того, як вона почала підтримувати двійкові типи даних. В результаті ці дві функції використовують рядки для представлення двійкових даних, при чому кодова точка кожного символу представляє значення кожного байта. Це призвело до поширеного неправильного розуміння, нібиbtoa
можна використовувати для кодування довільних текстових даних – наприклад, створення Base64data:
URL текстового чи HTML-документа.Проте відповідність між байтами та кодовими точками надійно виконується лише для кодових точок до
0x7f
. Крім того, кодові точки понад0xff
призведуть до викидання помилкиbtoa
, через перевищення максимального значення для 1 байта. Наступний розділ детально описує, як обійти це обмеження при кодуванні довільного тексту Unicode.
"Проблема Unicode"
Оскільки btoa
тлумачить кодові точки вихідного рядка як значення байтів, виклик btoa
для рядка призведе до викидання помилки "Character Out Of Range" ("символ поза допустимим діапазоном"), якщо кодова точка символу перевищує 0xff
. Для випадків використання, де потрібно закодувати довільний текст Unicode, необхідно спочатку перетворити рядок на його складові байти в UTF-8, а потім закодувати ці байти.
Найпростіше рішення – використати TextEncoder
і TextDecoder
для перетворення між UTF-8 та однобайтовими представленнями рядка:
function base64ToBytes(base64) {
const binString = atob(base64);
return Uint8Array.from(binString, (m) => m.codePointAt(0));
}
function bytesToBase64(bytes) {
const binString = Array.from(bytes, (byte) =>
String.fromCodePoint(byte),
).join("");
return btoa(binString);
}
// Usage
bytesToBase64(new TextEncoder().encode("a Ā 𐀀 文 🦄")); // "YSDEgCDwkICAIOaWhyDwn6aE"
new TextDecoder().decode(base64ToBytes("YSDEgCDwkICAIOaWhyDwn6aE")); // "a Ā 𐀀 文 🦄"
Перетворення довільних двійкових даних
Функції bytesToBase64
та base64ToBytes
з попереднього розділу можна використовувати безпосередньо для перетворення між рядками Base64 і Uint8Array
.
Задля кращої швидкодії асинхронне перетворення між URL з даними Base64 можна виконувати безпосередньо у вебплатформі за допомогою API FileReader
і fetch
:
async function bytesToBase64DataUrl(bytes, type = "application/octet-stream") {
return await new Promise((resolve, reject) => {
const reader = Object.assign(new FileReader(), {
onload: () => resolve(reader.result),
onerror: () => reject(reader.error),
});
reader.readAsDataURL(new File([bytes], "", { type }));
});
}
async function dataUrlToBytes(dataUrl) {
const res = await fetch(dataUrl);
return new Uint8Array(await res.arrayBuffer());
}
// Використання
await bytesToBase64DataUrl(new Uint8Array([0, 1, 2])); // "data:application/octet-stream;base64,AAEC"
await dataUrlToBytes("data:application/octet-stream;base64,AAEC"); // Uint8Array [0, 1, 2]
Дивіться також
- API JavaScript:
Window.atob()
(також доступна у воркерах)Window.btoa()
(також доступна у воркерах)
- URL даних
- Base64 на Вікіпедії
- Алгоритм Base64, описаний у RFC 4648