PHP: How to zip/unzip files

Updated: January 11, 2024 By: Guest Contributor Post a comment

Overview

PHP, as a versatile scripting language, provides robust functionalities to handle file compression and decompression operations. Compressing files into a .zip format not only saves space but also makes it easier to transport and distribute multiple files. Similarly, the ability to decompress or unzip files is essential for accessing the contents of zipped archives. This tutorial covers the essentials of working with zip archives in PHP, from the basics of creating and extracting zip files to more advanced topics such as managing file streams.

Before diving into the code, make sure you have PHP installed and the `ZipArchive` class is available in your environment. The `ZipArchive` class is not enabled by default in all PHP installations. You may need to install the `php-zip` extension or uncomment the respective line in your `php.ini` configuration file.

Creating a Zip File

To create a zip file, you will be using the `ZipArchive` class. Here’s a simple PHP script to zip a single file:

<?php
$zip = new ZipArchive();
$filename = './my-archive.zip';

if ($zip->open($filename, ZipArchive::CREATE) === TRUE) {
    $zip->addFile('path/to/file-to-zip.txt', 'file-to-zip.txt');
    $zip->close();
    echo 'Archive created!';
} else {
    echo 'Failed to create archive.';
}
?>

This opens a new zip file for writing and adds a single file to it. The `addFile` method takes two arguments: the path to the file on the disk and the name that will be used inside the zip archive.

Adding Multiple Files to a Zip Archive

Here is how you can add multiple files to a zip archive:

<?php
$files_to_zip = array(
    'path/to/first/file.txt',
    'path/to/second/file.jpg',
    // more files
);
$zip = new ZipArchive();
$filename = './my-archive.zip';

if ($zip->open($filename, ZipArchive::CREATE) === TRUE) {
    foreach ($files_to_zip as $file) {
        $zip->addFile($file, basename($file));
    }
    $zip->close();
    echo 'Archive created with multiple files!';
} else {
    echo 'Failed to create archive.';
}
?>

The `basename` function is used to extract the name of the file from the provided path, ensuring that the directory structure is not preserved in the zip archive.

Adding a Directory to a Zip Archive

Compressing a directory requires iterating over all the files within it, including subdirectories. Here’s a recursive approach to adding a directory:

<?php
function addFolderToZip($dir, $zipArchive, $zipdir = ''){
    if (is_dir($dir)) {
        if ($dh = opendir($dir)) {
            if (!empty($zipdir)) $zipArchive->addEmptyDir($zipdir);
            while (($file = readdir($dh)) !== false) {
                // Skip parent and root directories
                if($file != '.' && $file != '..'){
                    if (is_file($dir . $file)) {
                        $zipArchive->addFile($dir . $file, $zipdir . $file);
                    } elseif (is_dir($dir . $file)) {
                        addFolderToZip($dir . $file . '/', $zipArchive, $zipdir . $file . '/');
                    }
                }
            }
        }
    }
}

$zip = new ZipArchive();
$filename = './my-directory.zip';

if ($zip->open($filename, ZipArchive::CREATE) === TRUE) {
    addFolderToZip('./path/to/directory/', $zip);
    $zip->close();
    echo 'Directory zipped!';
} else {
    echo 'Failed to zip directory.';
}
?>

The `addFolderToZip` function encapsulates the logic for adding directories (including their contents) to the zip archive.

Extracting Zip Archives

To extract a zip file using PHP, the process is as straightforward as creating it. The following script will extract an archive to a specified directory:

<?php
$zip = new ZipArchive();
$filename = './my-archive.zip';

if ($zip->open($filename) === TRUE) {
    $zip->extractTo('./extracted-files/');
    $zip->close();
    echo 'Archive extracted!';
} else {
    echo 'Failed to extract archive.';
}
?>

The `extractTo` function accepts the path to the directory where you want to extract the archive’s contents. Make sure the directory exists and is writable.

Advanced ZIP Functionality

The `ZipArchive` class also offers more advanced capabilities such as setting passwords for encrypted archives, reading file comments, and modifying existing archives. Delving into these features requires additional code.

Below is an example demonstrating some of these advanced features:

  1. Creating an Encrypted ZIP Archive: This requires PHP 7.2 or later, as password encryption for ZIP archives was introduced in this version.
  2. Reading File Comments: Accessing comments added to files within the ZIP archive.
  3. Modifying an Existing Archive: Adding and removing files from an existing ZIP archive.

Here’s a PHP code snippet demonstrating these functionalities:

<?php
$zip = new ZipArchive();

// Creating a new ZIP file
$zipFileName = 'example.zip';
if ($zip->open($zipFileName, ZipArchive::CREATE) === TRUE) {
    // Add a file to the ZIP file
    $zip->addFromString('test.txt', 'This is a test file content');

    // Setting a password for the ZIP file (requires PHP 7.2+)
    $zip->setPassword('your_secure_password');

    // Closing the ZIP file
    $zip->close();
    echo "ZIP file created.\n";
} else {
    echo "Failed to create ZIP file.\n";
}

// Opening an existing ZIP file
if ($zip->open($zipFileName) === TRUE) {
    // Reading comments (if any)
    for ($i = 0; $i < $zip->numFiles; $i++) {
        $filename = $zip->getNameIndex($i);
        $comment = $zip->getCommentName($filename);
        echo "File: $filename, Comment: $comment\n";
    }

    // Adding a new file to the existing ZIP archive
    if ($zip->addFromString('newfile.txt', 'Content for new file')) {
        echo "File 'newfile.txt' added.\n";
    }

    // Deleting a file from the ZIP archive
    if ($zip->deleteName('test.txt')) {
        echo "File 'test.txt' deleted.\n";
    }

    $zip->close();
} else {
    echo "Failed to open ZIP file.\n";
}
?>

This script:

  • Creates a new ZIP file named example.zip and adds a file test.txt to it.
  • Sets a password for the ZIP archive. Remember, this feature requires PHP 7.2 or later.
  • Opens the existing ZIP file, reads comments for each file (if any), adds a new file, and deletes an existing file.

Important Notes:

  • PHP’s Zip extension must be installed and enabled to use the ZipArchive class.
  • The password encryption feature only encrypts the file contents, not the file names within the archive.
  • Always test ZIP functionalities in a safe, controlled environment before deploying them in a production scenario.
  • Make sure to handle errors and exceptions in a production environment for robustness.

Conclusion

Whether you’re building a content management system, a backup utility, or a bulk file downloader, knowing how to handle zip operations in PHP is indispensable. By leveraging PHP’s `ZipArchive` class, you can easily integrate zip functionality into your applications, providing a better experience for your users and an efficient means of handling files in your code.