W3docs

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:

MethodeZweck
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) / numFilesUntersucht 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() oder addFromString() vornehmen, werden erst auf die Festplatte geschrieben, wenn Sie close() aufrufen. Wenn close() 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 Fehler false zurück. Bei einem Fehler gibt es einen ganzzahligen Fehlercode zurück (z. B. ZipArchive::ER_NOENT, wenn die Datei fehlt). Der strikte Vergleich mit === true ist 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/passwd das 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 Sie extractTo() oder streamen Sie mit getStream().

Verwandte Themen

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.

Übungen

Übung
Welche der folgenden Aussagen über die ZIP-Erweiterung in PHP sind zutreffend?
Welche der folgenden Aussagen über die ZIP-Erweiterung in PHP sind zutreffend?
Was this page helpful?