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.
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.
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.
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;
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.
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.
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);
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.
Hinterlasse mir gerne einen Kommentar zum Artikel und wie er dir weitergeholfen hat beziehungsweise, was dir helfen würde das Thema besser zu verstehen. Oder hast du einen Fehler entdeckt, den ich korrigieren sollte? Schreibe mir auch dazu gerne ein Feedback!
Es sind noch keine Kommentare vorhanden? Sei der/die Erste und verfasse einen Kommentar zum Artikel "Arbeiten in PHP mit ZIP-Archiven"!