Lerne Coding
Arbeiten in PHP mit ZIP-Archiven
31.12.2020

Arbeiten in PHP mit ZIP-Archiven

Inhaltsverzeichnis
[[TABLE OF CONTENTS]]
access_timeGeschätzte Lesezeit ca. Minuten

ZIP-Dateien sind ein Container- und Archiv-Format. Mit ihnen kannst du Dateien verlustfrei komprimieren und so als Backup-Format bzw. Datenaustauschformat nutzen. Zum Beispiel sind ZIP-Dateien sehr gut dafür geeignet, um mehrere Dateien an eine Email anzuhängen oder um mehrere Ordner zu verschicken, wo die Ordnerstruktur beibehalten werden soll.

Falls du eher Interesse daran hast, mit Python und ZIP-Dateien zu arbeiten, empfehle ich dir den folgenden Artikel von mir "ZIP-Dateien erstellen und lesen mit Python".

Um mit ZIP-Dateien/Archiven in PHP zu arbeiten, benötigen wir die Klasse/das Paket ZipArchive. Dieses beinhaltet alle notwendigen Methoden, um mit ZIP-Dateien in PHP arbeiten zu können.

Einen Ordner in PHP als ZIP-Datei verpacken

Nun wollen wir mal mit dem ersten Beispiel starten. Hierbei geht es darum, einen Ordner als ZIP-Datei zu verpacken. Dafür gibt es leider keine Fertigfunktion, weshalb ich eine entsprechende Funktion erstellt habe. Um alle Dateien aus dem Ordner zu erhalten, verwenden wir einen RecursiveIteratorIterator und einen RecuriveDirectoryIterator. Dabei ist zu beachten, dass wir die Flag FilesystemIterator::SKIP_DOT setzen, damit wir keine . und .. über den Iterator erhalten. Die Variable $files ist nun unser Iterator, den wir später verwenden können, um jede Datei aus dem Ordner in die ZIP-Datei einzufügen.

Anschließend öffnen wir unsere ZIP-Datei mit der Flag ZipArchive::CREATE, um ein neues ZIP-Archive zu erstellen. Wichtig: hierbei ist immer eine if-Abfrage zu verwenden, da diese Methode nur bei Erfolg true zurückgibt. So können wir mögliche Fehler verhindern. Anschließend verwenden wir einen foreach-Loop, um alle Dateien in das ZIP-Archive einzufügen. Abschließend schließen wir die ZIP-Datei noch, womit wir dann mit dem Erstellen einer ZIP-Datei aus unserem Ordner fertig wären.

Um noch final zu prüfen, dass die Datei abgelegt worden ist, lassen wir uns den Status zurückgeben, ob die ZIP-Datei existiert.

<?php

function zipFolder(string $folder,string $target){
    $files  = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($folder,FilesystemIterator::SKIP_DOTS));
    $zip    = new ZipArchive;
    $create = $target . '.zip';

    if($zip->open($create,ZipArchive::CREATE)):

        foreach($files as  $file):
            $zip->addFile(realpath($file),$file);

            print($file . " - Datei Hinzugefügt ". PHP_EOL);
        endforeach;

        $zip->close();    
    endif;

    return file_exists($create);
}

if(zipFolder('bilder','bilder-archive')):
    print("ZIP File Erstellt");
endif;

Wenn das Erstellen der ZIP erfolgreich war, erhalten wir eine entsprechende Meldung in unserer Ausgabe.

Ein ZIP-Archive in ein Verzeichnis entpacken

Um ein ZIP-Archive in PHP zu entpacken, benötigen wir die Methode extractTo. Bei dieser können wir als ersten Parameter unseren Pfad angeben, wo der Ordner entpackt werden soll. Als zweiten optionalen Parameter kann ein String oder Array von bestimmten Dateien, die wir entdecken wollen, angeben werden. Das ist für den Fall praktisch, wenn wir schon wissen, dass wir nur eine bestimmte Datei benötigen.

<?php

$zip = new ZipArchive();

if($zip->open('bilder-archive.zip')):
    $zip->extractTo('bilder-archive');
    $zip->close();
endif;

Nun ist unser ZIP-Archive in das Verzeichnis bilder-archive entpackt.

Dateien aus einer ZIP-Datei lesen, ohne diese zu extrahieren

Manchmal weißt du, dass du bestimmte ZIP-Dateien bekommst, die vielleicht von einem Export eines bestimmten Programms kommen. Und du benötigst eigentlich nur eine spezifische Datei bzw. deren Inhalt, zum Beispiel eine JSON- oder XML-Datei. Dann kannst du auch direkt auf diese Datei zugreifen, ohne dass das ZIP-Archive entpackt werden muss. Das ist vor allem dann nützlich, wenn du nur einen Import-Prozess hast, der nur einmalig auf Inhalte aus der ZIP-Datei zugreifen muss, und du den Ordner mit dem entpackten ZIP-Archive am Ende des Prozesses sowieso wieder löschen würdest. Dafür hat die Klasse ZipArchive die Methode getFromName. Diese Methode erwartet einen Pfad zur Datei im ZIP-Ordner. In unserem Beispiel holen wir uns eine Textdatei und geben dann den Content davon aus. In der Variable ist dann der String entsprechend gespeichert.

<?php
$zip =  new ZipArchive();

if($zip->open('bilder-archive.zip')):
    $content = $zip->getFromName('bilder/test.txt');

    echo $content;

    $zip->close();
endif;

ZIP-Dateien mit Passwort entpacken

Natürlich kannst du auch ZIP-Archive entpacken, die einen Passwortschutz haben. Dafür ist es nur notwendig, die Methode setPassword zu verwenden und entsprechend das Passwort anzugeben. Dann wird das ZIP-Archive wie gewohnt entpackt.

<?php
# ZIP Datei mit Passwort zu Entpacken

$zip = new ZipArchive();

if($zip->open('bilder-archive-pwd.zip')):
    $zip->setPassword('passwort');
    $zip->extractTo('bilder-archiv-passwort');
    $zip->close();
endif;

Wichtig: wenn du kein Passwort bei einem ZIP-Archive mit Passwort setzt, wird in PHP der Ordner trotzdem erstellt und es kommt keine Fehlermeldung, dass das ZIP-Archive passwortgeschützt ist.

ZIP-Archive mit Passwortschutz erstellen

Um nun ein Archive mit Passwortschutz (Encryption) zu erstellen, benötigen wir zwei Methoden. Diese sind setPassword und setEncryptionName. Für das Beispiel habe ich die Funktion aus dem ersten Beispiel um einen Passwortparameter erweitert.

Nun wird, nachdem das ZIP geöffnet wurde, mit setPassword das Standardpasswort definiert. Theoretisch kann man dieses auch bei der Methode setEncryptionName als dritten Parameter einsetzen. So könnte man jeder Datei ein anderes Passwort im ZIP-Archive geben.

Für unseren Fall wollen wir aber ein Passwort für den gesamten Order setzen. Anschließend müssen wir jeder Datei noch sagen, dass die Verschlüsselungsmethode AES 256 verwendet werden soll.

Durch diese Anpassungen an der Funktion können wir nun als dritten Parameter optional ein Passwort angeben.

<?php

function zipFolder(string $folder,string $target,string $password = ""):bool{
    $files  = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($folder,FilesystemIterator::SKIP_DOTS));
    $zip    = new ZipArchive;
    $create = $target . '.zip';

    if($zip->open($create,ZipArchive::CREATE)):

        if(!empty($password)):
            $zip->setPassword($password);
        endif;

        foreach($files as  $file):
            $zip->addFile(realpath($file),$file);

            if(!empty($password)):
                $zip->setEncryptionName($file, ZipArchive::EM_AES_256);
            endif;

            print($file . " - Datei Hinzugefügt ". PHP_EOL);
        endforeach;

        $zip->close();    
    endif;

    return file_exists($create);
}

if(zipFolder('bilder','bilder-archive-pwd','passwort')):
    print("ZIP File Erstellt");
endif;

Wichtig: die Option setEncryptionName ist erst ab PHP 7.2 verfügbar. Das heißt, davor ist es nicht möglich, ein passwortgeschütztes ZIP-Archive zu erstellen.

Probleme mit großen Ordnern

Manchmal kann es vorkommen, dass du einen 500er Fehler bekommst, wenn du ein ZIP-Archive von einem sehr großen Ordner erstellen willst. Das liegt daran, dass die max_execution_time überschritten wird. In diesem Fall kannst du einfach vorher die max_execution_time entsprechend erhöhen, zum Beispiel auf 4 Minuten. Am besten passt du für diesen Fall die Zeit erst kurz vor dem ZIP-Prozess an und nicht schon am Anfang, sodass andere Prozesse trotzdem noch wegen einer zu langen Ausführungszeit fehlschlagen können.

ini_set('max_execution_time', 240);

Abschließende Worte

Das Arbeiten mit ZIP-Dateien funktioniert wirklich sehr einfach in PHP. Du kannst einfach ZIP-Archive mit Passwort erstellen und lesen. Du kannst Ordner als ZIP-Datei verpacken und vieles mehr. Auch nur eine bestimmte Datei aus dem ZIP-Archive zu lesen ist möglich.

Ich hoffe, ich konnte dir mit dieser Anleitung weiterhelfen, sodass du nun bestens Bescheid weißt und mit ZIP-Archiven in PHP arbeiten kannst.

Bildquelle - Vielen Dank an die Ersteller:innen für dieses Bild
Kommentare zum Artikel

Es sind noch keine Kommentare vorhanden? Sei der/die Erste und verfasse einen Kommentar zum Artikel "Arbeiten in PHP mit ZIP-Archiven"!

Kommentar schreiben

Vom Autor Empfohlen
close