PHP Zip
ZIP-Archive sind komprimierte Dateien. Erfahren Sie, wie Sie mit der ZipArchive-Klasse in PHP Archive erstellen, lesen und entpacken.
Ein ZIP-Archiv ist eine Datei, die eine oder mehrere Dateien bündelt und mit dem ZIP-Algorithmus komprimiert. Archive werden häufig verwendet, um Download-Größen zu reduzieren, zusammengehörige Dateien in einer einzigen verteilbaren Einheit zu gruppieren und Daten zu sichern. Ein ZIP-Archiv trägt normalerweise die Dateiendung .zip.
Dieses Kapitel zeigt, wie man ZIP-Archive in modernem PHP mit der eingebauten Klasse ZipArchive erstellt, liest und entpackt — mit ausführbaren Beispielen und den wichtigsten Fallstricken.
Die ZipArchive-Klasse
Die veralteten prozeduralen zip_*-Funktionen wurden in PHP 7.4 als veraltet markiert und in PHP 8.0 entfernt. Moderner Code sollte die objektorientierte Klasse ZipArchive verwenden, die Teil der mitgelieferten zip-Erweiterung ist (aktivieren Sie ext-zip, falls noch nicht geschehen — prüfen Sie dies mit extension_loaded('zip')).
Die am häufigsten verwendeten Methoden sind:
| Methode | Zweck |
|---|---|
open($filename, $flags) | Öffnet ein Archiv zum Lesen oder Schreiben. Gibt true oder einen Fehlercode zurück. |
addFile($path, $entryName) | Fügt eine Datei vom Dateisystem zum Archiv hinzu. |
addFromString($entryName, $contents) | Fügt einen Eintrag aus einem im Speicher befindlichen String hinzu. |
addEmptyDir($dirName) | Fügt einen leeren Verzeichniseintrag hinzu. |
extractTo($directory, $entries) | Entpackt alle Einträge (oder eine ausgewählte Teilmenge) in ein Verzeichnis. |
getFromName($entryName) | Liest einen Eintrag in einen String, ohne die Festplatte zu berühren. |
statIndex($i) / numFiles | Untersucht Einträge und zählt sie. |
getStatusString() | Gibt eine lesbare Statusmeldung für die Fehlerbehandlung zurück. |
close() | Schreibt ausstehende Änderungen und schließt das Handle. |
Wichtig: Änderungen, die Sie mit
addFile()oderaddFromString()vornehmen, werden erst auf die Festplatte geschrieben, wenn Sieclose()aufrufen. Wennclose()vergessen wird, entsteht ein leeres oder beschädigtes Archiv.
Ein ZIP-Archiv erstellen
Übergeben Sie das Flag ZipArchive::CREATE, um ein neues Archiv zu erstellen, und fügen Sie ZipArchive::OVERWRITE hinzu, um neu zu beginnen, falls bereits eine Datei mit diesem Namen existiert:
$zip = new ZipArchive();
$zipName = 'documents.zip';
if ($zip->open($zipName, ZipArchive::CREATE | ZipArchive::OVERWRITE) === true) {
// Add an entry from a string (no temp file needed).
$zip->addFromString('readme.txt', "Hello from PHP!\n");
// Add a file from disk, optionally under a folder inside the archive.
$zip->addFile('report.csv', 'data/report.csv');
// Add an empty directory entry.
$zip->addEmptyDir('logs');
echo "Adding {$zip->numFiles} entries to {$zipName}.\n";
$zip->close(); // Must be called for the archive to be written.
echo "Archive saved.\n";
} else {
echo "Could not create the archive.\n";
}Vorausgesetzt, report.csv existiert, gibt dies aus:
Adding 3 entries to documents.zip.
Archive saved.Lesen Sie numFiles vor close() — nachdem das Handle geschlossen wurde, spiegelt das Objekt den Eintragsanzahl nicht mehr wider.
Einträge ohne Entpacken lesen
Sie können den Inhalt eines Archivs untersuchen oder einen einzelnen Eintrag in den Speicher laden, ohne alles auf die Festplatte zu entpacken:
$zip = new ZipArchive();
if ($zip->open('documents.zip') === true) {
for ($i = 0; $i < $zip->numFiles; $i++) {
$entry = $zip->statIndex($i);
echo $entry['name'] . ' (' . $entry['size'] . " bytes)\n";
}
// Read one entry straight into a string.
echo "---\n" . $zip->getFromName('readme.txt');
$zip->close();
}Ausgabe:
readme.txt (16 bytes)
data/report.csv (20 bytes)
logs/ (0 bytes)
---
Hello from PHP!Ein Archiv auf die Festplatte entpacken
extractTo() entpackt das Archiv. Überprüfen Sie immer den Rückgabewert und melden Sie Fehler mit getStatusString():
$zip = new ZipArchive();
$filename = 'documents.zip';
$extractTo = './extracted_files';
if ($zip->open($filename) === true) {
if (!is_dir($extractTo)) {
mkdir($extractTo, 0755, true);
}
if ($zip->extractTo($extractTo) === true) {
echo "Archive extracted successfully.";
} else {
echo "Extraction failed: " . $zip->getStatusString();
}
$zip->close();
} else {
echo "Failed to open archive.";
}Um nur bestimmte Dateien zu entpacken, übergeben Sie ihre Namen als zweites Argument:
$zip->extractTo($extractTo, ['readme.txt', 'data/report.csv']);Häufige Fallstricke
- Rufen Sie immer
close()auf. Bis dahin liegen Hinzufügungen nur im Speicher vor, und die Datei auf der Festplatte kann leer sein. open()gibt nicht bei jedem Fehlerfalsezurück. Bei einem Fehler gibt es einen ganzzahligen Fehlercode zurück (z. B.ZipArchive::ER_NOENT, wenn die Datei fehlt). Der strikte Vergleich mit=== trueist der sichere Weg, um Erfolg zu erkennen.- Zip Slip. Beim Entpacken nicht vertrauenswürdiger Archive kann ein bösartiger Eintrag mit einem Namen wie
../../etc/passwddas Zielverzeichnis verlassen. Überprüfen oder bereinigen Sie Eintragsnames, bevor Sie Dateien entpacken, die Sie nicht selbst erstellt haben. - Speicher.
getFromName()lädt den gesamten Eintrag in den Speicher; für große Einträge bevorzugen SieextractTo()oder streamen Sie mitgetStream().
Verwandte Themen
- PHP file_put_contents() — die aus einem Archiv gelesenen Daten wieder auf die Festplatte schreiben.
- PHP file_get_contents() — ganze Dateien lesen, z. B. bevor sie einem ZIP hinzugefügt werden.
- PHP file_exists() — sicherstellen, dass eine Datei vorhanden ist, bevor
addFile()aufgerufen wird. - PHP fread() — Dateiinhalte in Blöcken lesen.
Fazit
Die Klasse ZipArchive ist der moderne und zuverlässige Weg, um in PHP mit ZIP-Archiven zu arbeiten. Sie können Archive mit addFile() und addFromString() erstellen, sie mit numFiles und statIndex() untersuchen, einzelne Einträge mit getFromName() in den Speicher laden und sie mit extractTo() entpacken — immer daran denken, close() aufzurufen und beim Entpacken nicht vertrauenswürdige Eintragsnames abzusichern.