Einen String kodieren und dekodieren
PHP-Strings sind Bytestrings, base64_encode kodiert also genau die Bytes, die der String enthält. Eine als UTF-8 gespeicherte Quelldatei liefert Ihnen UTF-8-Base64 ohne Umwandlungsschritt:
<?php
$enc = base64_encode("héllo wörld");
echo $enc; // aMOpbGxvIHfDtnJsZA==
echo base64_decode($enc); // héllo wörld
Kommt Text aus einer Datenbank oder einem Formular in einem anderen Zeichensatz, wandeln Sie ihn zuerst mit mb_convert_encoding($s, 'UTF-8', 'Windows-1252') um. Sonst ist das Base64 für diese Bytes zwar korrekt, ergibt anderswo dekodiert aber Zeichensalat. Mit dem Tool Base64 in Text können Sie verschiedene Zeichensätze auf das Ergebnis anwenden.
Strict-Modus: base64_decode($s, true)
Ohne das zweite Argument wirft base64_decode jedes Zeichen weg, das nicht im Alphabet steht, und dekodiert den Rest. Mit true gibt es stattdessen false zurück:
var_dump(base64_decode("aGk=!!")); // string(2) "hi"
var_dump(base64_decode("aGk=!!", true)); // bool(false)
Prüfen Sie immer mit ===, denn eine gültige leere Eingabe ergibt "", und das ist falsy:
$bytes = base64_decode($input, true);
if ($bytes === false) {
throw new InvalidArgumentException('Invalid Base64');
}
Der Strict-Modus ist weniger streng, als der Name vermuten lässt. Getestet mit PHP 8.4:
| Eingabe | Ergebnis im Strict-Modus |
|---|---|
aGk (ohne Padding) | "hi" |
"aGk=\n" (abschließender Zeilenumbruch) | "hi" |
aGl= (Padding-Bits ungleich null) | "hi" |
aGk== (überzähliges Padding) | false |
a (unmögliche Länge) | false |
PDw_Pz8-Pg== (URL-sichere Zeichen) | false |
Brauchen Sie ausschließlich kanonisches Base64, entfernen Sie Leerraum, dekodieren im Strict-Modus und prüfen dann base64_encode($bytes) === $input. Der Base64-Validator führt dieselben Prüfungen aus und zeigt auf das fehlerhafte Zeichen.
URL-sicheres Base64 mit und ohne Padding
PHP hat keine eingebaute Base64URL-Funktion. Tauschen Sie die beiden Zeichen mit strtr, das bei Abbildungen einzelner Zeichen schneller ist als str_replace:
function b64url_encode(string $data, bool $pad = false): string {
$s = strtr(base64_encode($data), '+/', '-_');
return $pad ? $s : rtrim($s, '=');
}
function b64url_decode(string $s): string|false {
return base64_decode(strtr($s, '-_', '+/'), true);
}
echo b64url_encode("<<???>>"); // PDw_Pz8-Pg
echo b64url_encode("<<???>>", true); // PDw_Pz8-Pg==
echo b64url_decode("PDw_Pz8-Pg"); // <<???>>
Da der Strict-Modus fehlendes Padding toleriert, müssen Sie vor dem Dekodieren kein = ergänzen. Mehr zu den Unterschieden unter Base64 vs. Base64URL.
Eine Datei kodieren und dekodieren
echo base64_encode(file_get_contents("hello.txt")); // aGVsbG8K
file_put_contents("copy.txt", base64_decode("aGVsbG8K", true));
Für eine Data-URI stellen Sie den MIME-Typ voran: 'data:image/png;base64,' . base64_encode($png). Ist fileinfo aktiviert, kann mime_content_type($path) den Typ erkennen.
Große Dateien mit Stream-Filtern
file_get_contents lädt die ganze Datei plus die Base64-Kopie, der Speicherbedarf liegt also bei etwa dem 2,3-Fachen der Dateigröße. Der Stream-Filter convert.base64-encode kodiert beim Kopieren:
$in = fopen("big.bin", "rb");
$out = fopen("big.b64", "wb");
stream_filter_append($out, "convert.base64-encode");
stream_copy_to_stream($in, $out);
fclose($in);
fclose($out);
Das Dekodieren funktioniert genauso oder in einer Zeile über eine php://filter-URL:
copy("php://filter/read=convert.base64-decode/resource=big.b64", "big.out");
Beide lieferten bei einer 300-KB-Testdatei dieselbe Ausgabe wie die Funktionen im Speicher. Eine eigene Schleife funktioniert ebenfalls, wenn jeder Block ein Vielfaches von 3 Bytes ist, zum Beispiel fread($in, 3 * 8192). Jede andere Größe setzt = mitten in die Ausgabe.
MIME-Zeilenumbruch
E-Mail-Inhalte brauchen Zeilen mit höchstens 76 Zeichen. Genau das macht chunk_split, standardmäßig mit \r\n als Zeilenende:
echo chunk_split(base64_encode(str_repeat("x", 60)));
// eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4
// eHh4
Es hängt außerdem ein abschließendes \r\n an. Mail-Bibliotheken erledigen das für Sie; der MIME-Base64-Encoder zeigt das Format.
Häufige Fallstricke
- Strict-Modus vergessen bei nicht vertrauenswürdigen Eingaben. Fehlerhafte Daten werden zu zufälligen Bytes dekodiert und scheitern irgendwo weit entfernt von der Ursache.
- URL-sichere Eingabe im Standardmodus.
base64_decode("PDw_Pz8-Pg==")liefertstring(6) "<<���", nicht<<???>>. Übersetzen Sie vorher mitstrtr. nullübergeben. Ab PHP 8.1 erhalten SieDeprecated: base64_encode(): Passing null to parameter #1 ($string) of type string is deprecated. Ein Array wirftTypeError: base64_encode(): Argument #1 ($string) must be of type string, array given.+wird zum Leerzeichen. Standard-Base64 in einem Query-String wird durch das URL-Dekodieren verstümmelt, weil+dort ein Leerzeichen bedeutet. Verwenden Sie die URL-sichere Variante oderrawurlencode.- Als Passwortspeicher verwenden. Base64 verbirgt nichts. Verwenden Sie
password_hashfür Passwörter und lesen Sie Kodierung vs. Verschlüsselung.
Versionshinweise
base64_encode,base64_decodeund das Flag$strictgibt es in allen unterstützten PHP-Versionen (der Strict-Modus kam mit 5.2).- Seit PHP 8.0 ist der Rückgabetyp von
base64_decodealsstring|falsedeklariert, und ein Array oder Objekt wirft einenTypeErrorstatt einer Warnung. - Der Filter
convert.base64-encodeakzeptiert die Optionenline-lengthundline-break-charsfür MIME-Ausgabe, zum Beispielstream_filter_append($out, 'convert.base64-encode', STREAM_FILTER_WRITE, ['line-length' => 76, 'line-break-chars' => "\r\n"]).
Häufige Fragen
Was bewirkt der zweite Parameter von base64_decode?
base64_decode($s, true) aktiviert den Strict-Modus: Die Funktion gibt false zurück, wenn die Eingabe Zeichen außerhalb des Base64-Alphabets enthält. Ohne ihn werden diese Zeichen stillschweigend verworfen.
Hat PHP eine Funktion base64url_encode?
Nein. Kodieren Sie mit rtrim(strtr(base64_encode($data), '+/', '-_'), '=') und dekodieren Sie mit base64_decode(strtr($s, '-_', '+/'), true). Der Strict-Modus akzeptiert das fehlende Padding.
Ist der Strict-Modus von base64_decode ein vollständiger Validator?
Nein. Er akzeptiert weiterhin Leerraum, fehlendes Padding und Padding-Bits ungleich null wie bei aGl=. Für eine exakte Prüfung kodieren Sie das Ergebnis erneut und vergleichen es mit der normalisierten Eingabe.
Warum liefert base64_decode Datenmüll statt false?
Wahrscheinlich haben Sie es ohne true aufgerufen. Im Standardmodus verwirft base64_decode('PDw_Pz8-Pg==') das _ und das - und liefert sechs falsche Bytes. Übersetzen Sie URL-sichere Eingaben vorher mit strtr.