ZipArchive
| Language | PHP |
|---|---|
| License | PHP License (extension), BSD 3-clause (libzip) |
| Repository | github.com/pierrejoye/php_zip (also bundled in php-src) |
| Documentation | php.net: ZipArchive |
| Depends on | libzip |
| Read / write | yes / yes, ZIP64, stored, DEFLATE, and bzip2 / LZMA / XZ / Zstandard if libzip has them; AES and ZipCrypto |
ZipArchive is the class of the zip extension, a wrapper around libzip. It opens an archive, collects changes (add, rename, delete, set comment, set encryption) and writes them when you call close(). Most PHP builds and distributions include the extension.
Like libzip, it modifies archives by writing a new file on close(); a large archive needs free disk space for the temporary copy.
Installation#
Shell
# Debian / Ubuntu
sudo apt install php-zip
# Fedora
sudo dnf install php-pecl-zip
# compile PHP with
./configure --with-zip
On Windows, enable extension=zip in php.ini. Check with php -m | grep zip.
Basic usage: extract and create a ZIP#
PHP
<?php
$zip = new ZipArchive();
// extract
if ($zip->open('in.zip') !== true) {
die("cannot open in.zip\n");
}
$zip->extractTo('out');
$zip->close();
// create
if ($zip->open('out.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
die("cannot create out.zip\n");
}
$zip->addFile('report.pdf', 'docs/report.pdf');
$zip->addFromString('hello.txt', "hello from PHP\n");
$zip->close(); // the archive is written here
open() returns true or an error code (ZipArchive::ER_NOENT, ER_NOZIP, …), so compare with !== true.
How to list the files in a ZIP#
PHP
<?php
$zip = new ZipArchive();
$zip->open('in.zip', ZipArchive::RDONLY);
for ($i = 0; $i < $zip->numFiles; $i++) {
$st = $zip->statIndex($i);
printf("%-40s %10d -> %10d %s\n", $st['name'], $st['size'], $st['comp_size'], date('Y-m-d H:i', $st['mtime']));
}
$zip->close();
How to read one file from a ZIP#
PHP
<?php
$zip = new ZipArchive();
$zip->open('in.zip', ZipArchive::RDONLY);
$text = $zip->getFromName('docs/readme.txt'); // false if missing
if ($text !== false) {
echo $text;
}
// stream a large entry
$fp = $zip->getStream('data/big.csv');
while (($line = fgets($fp)) !== false) {
// process $line
}
fclose($fp);
$zip->close();
Without opening the archive first, the zip:// stream wrapper reads one entry: file_get_contents('zip://in.zip#docs/readme.txt').
How to zip a whole folder#
PHP
<?php
$zip = new ZipArchive();
$zip->open('photos.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE);
$zip->addGlob('photos/*.jpg', 0, ['remove_all_path' => true]);
// recursive: walk the directory yourself
$it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator('docs', FilesystemIterator::SKIP_DOTS));
foreach ($it as $file) {
$zip->addFile($file->getPathname(), str_replace('\\', '/', $file->getPathname()));
}
$zip->close();
How to create and extract an AES-encrypted ZIP#
PHP
<?php
$zip = new ZipArchive();
$zip->open('secret.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE);
$zip->addFromString('secret.txt', 'top secret');
$zip->setEncryptionName('secret.txt', ZipArchive::EM_AES_256, 'my password');
$zip->close();
$zip->open('secret.zip');
$zip->setPassword('my password');
$zip->extractTo('out');
$zip->close();
How to set the compression method#
PHP
$zip->addFile('data.csv');
$zip->setCompressionName('data.csv', ZipArchive::CM_DEFLATE, 9);
// ZipArchive::CM_STORE for already compressed files;
// CM_ZSTD, CM_XZ, CM_LZMA, CM_BZIP2 if ZipArchive::isCompressionMethodSupported() says so
Tips#
extractTocleans entry names (removes..components and leading/), so files stay inside the target folder. If you write entries yourself withgetStream, clean the names the same way.$zip->deleteName('old.log')and$zip->renameName('a.txt', 'b.txt')change existing archives.ZipArchive::RDONLY(PHP 7.4.3+) opens without write access, so a read-only file works.