Base64 im Browser und Node.js: ein Byte-Vertrag, zwei APIs

Verwenden Sie TextEncoder in Browsern und Buffer in Node.js und testen Sie dann ihre Ausgaben mit denselben Unicode- und Binärgeräten.

Ein Browser-Client und ein Node.js-Dienst sollten denselben Base64 für dieselben Bytes erzeugen. Sie müssen dazu nicht dasselbe API verwenden. Die wichtige Vereinbarung ist die Byte-Darstellung von Text, das Alphabet und die Behandlung von Auffüllungen und ungültigen Eingaben.

Browser: Machen Sie den Schritt UTF-8 explizit

Die herkömmlichen Browserfunktionen arbeiten mit Byte-Strings. Konvertieren Sie Unicode-Text mit TextEncoder, dann kodieren Sie diese Bytes. Rekonstruieren Sie auf dem Rückpfad ein Byte-Array und dekodieren Sie UTF-8 explizit. In diesem Beispiel wird eine Schleife verwendet, um die Erweiterung eines großen Arrays in Funktionsargumente zu vermeiden, obwohl ein Produktionsdatei-Encoder weiterhin begrenzte Blöcke oder ein entsprechendes Byte API verwenden sollte.

const text = '中文😊';
const bytes = new TextEncoder().encode(text);
let binary = '';
for (const byte of bytes) binary += String.fromCharCode(byte);
const encoded = btoa(binary);
console.log(encoded); // 5Lit5paH8J+Yig==
const decodedBytes = Uint8Array.from(atob(encoded), c => c.charCodeAt(0));
const decoded = new TextDecoder('utf-8', { fatal: true }).decode(decodedBytes);
console.log(decoded); // 中文😊

Node.js: Behalten Sie Buffer an der Bytegrenze

Buffer.from(text, 'utf8') macht die Textkodierung sichtbar. Rufen toString('base64') stellt dann diese Bytes dar. Durch die Dekodierung in Buffer bleiben Binärdaten erhalten; Die sofortige Konvertierung in eine Zeichenfolge vom Typ UTF-8 ist nur dann sinnvoll, wenn bekannt ist, dass es sich bei der Nutzlast um Text handelt.

import { Buffer } from 'node:buffer';
const encoded = Buffer.from('中文😊', 'utf8').toString('base64');
console.log(encoded); // 5Lit5paH8J+Yig==
const bytes = Buffer.from(encoded, 'base64');
console.log(new TextDecoder('utf-8', { fatal: true }).decode(bytes)); // 中文😊

Die Option fatal von TextDecoder wird im Beispiel bewusst verwendet. Die übliche Umwandlung eines Buffers in eine UTF-8-Zeichenfolge kann bei ungültigen Eingaben Ersatzzeichen einfügen. Eine erfolgreiche Textanzeige würde dann verbergen, dass die ursprünglichen Bytes nicht originalgetreu dargestellt werden konnten.

Vereinbaren Sie die Validierung gesondert

Der Base64-Decoder des Knotens akzeptiert einige Eingabeformulare, die eine strengere Anwendung möglicherweise ablehnen würde. Verwenden Sie eine erfolgreiche Buffer-Konvertierung nicht als Beweis dafür, dass die kanonische Darstellung eines Protokolls bereitgestellt wurde. Wenn die genaue Syntax für Signaturen, Cache-Schlüssel oder interoperable Serialisierung wichtig ist, überprüfen Sie sie vor der Dekodierung.

Verwenden Sie für einen gemeinsamen Regressionstest ASCII, chinesische Zeichen, Emoji, ein Nullbyte, das Byte FF und alle Längen rund um eine Drei-Byte-Grenze. Vergleichen Sie die Bytes zwischen den Laufzeitumgebungen. Testen Sie auch die URL-sichere Ausgabe mit Testdaten, die tatsächlich die ersetzten Zeichen enthalten. Eine Eingabe, deren Ausgabe nur Buchstaben enthält, kann nicht belegen, dass die Variantenoption funktioniert.

Behalten Sie beim Lesen von Dateien in Node den zurückgegebenen Wert Buffer bei, anstatt eine Textkodierung auf die gelesene Datei anzuwenden. Verwenden Sie im Browser File.arrayBuffer(). Diese kleinen Grenzentscheidungen vermeiden die meisten versehentlichen Korruptionen. Siehe Node.js Buffer für Knotenverhalten und MDN: btoa() für den Browser-Byte-String-Vertrag.