PHP: Zip a Directory and Automatically Download

Introduction

PHP provides built-in functionality to create ZIP archives using the ZipArchive class. This can be useful when you need to allow users to download multiple files and subdirectories as a single ZIP file.

In this article, we will explain how to compress a directory, including its files and subdirectories, into a ZIP archive and automatically download the generated ZIP file using PHP.

Prerequisites

Before proceeding, make sure the following requirements are available:

  1. PHP is installed and configured on the server.
  2. The PHP zip extension is enabled.
  3. The directory that needs to be compressed exists and is accessible by the PHP process.
  4. The PHP script has permission to create the ZIP file in the specified location.

Implementation

1. Define the Source Directory and ZIP File

Define the directory that needs to be compressed and the name of the ZIP file:

$dir = 'target';
$zip_file = 'file.zip';

Here:

  • $dir specifies the directory that needs to be compressed.
  • $zip_file specifies the name of the ZIP file that will be generated and downloaded.

2. Get the Directory Path

Use realpath() to obtain the absolute path of the source directory:

$rootPath = realpath($dir);

This provides the actual filesystem path required by the ZIP operation.

3. Initialize the ZIP Archive

Create a new ZipArchive object and open the ZIP file:

$zip = new ZipArchive();

$zip->open($zip_file, ZipArchive::CREATE | ZipArchive::OVERWRITE);

The CREATE option creates the ZIP file if it does not already exist, while OVERWRITE replaces an existing ZIP file.

4. Find Files and Subdirectories Recursively

Use RecursiveDirectoryIterator together with RecursiveIteratorIterator to process the source directory and its subdirectories:

$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($rootPath)
);

This allows PHP to iterate through all files contained within the directory, including files located inside subdirectories.

5. Add Files to the ZIP Archive

Use a foreach loop to add each file to the ZIP archive:

foreach ($files as $name => $file)
{
if (!$file->isDir())
{
$filePath = $file->getRealPath();
$relativePath = substr($filePath, strlen($rootPath) + 1);
$zip->addFile($filePath, $relativePath);
}
}

The script checks whether the current item is a file. If it is not a directory, the file is added to the ZIP archive.

The relative path ensures that the directory structure is maintained inside the ZIP file.

6. Close the ZIP Archive

After all files have been added, close the ZIP archive:

$zip->close();

7. Download the ZIP File Automatically

Set the appropriate HTTP headers and read the generated ZIP file:

header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . basename($zip_file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($zip_file));

readfile($zip_file);

These headers instruct the browser to download the generated ZIP file instead of displaying it.

Complete PHP Code

The complete PHP script is shown below:

open($zip_file, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== TRUE) {
exit('Unable to create ZIP file.');
}

$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($rootPath)
);

foreach ($files as $name => $file) {
if (!$file->isDir()) {
$filePath = $file->getRealPath();
$relativePath = substr($filePath, strlen($rootPath) + 1);

$zip->addFile($filePath, $relativePath);
}
}

$zip->close();

if (file_exists($zip_file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . basename($zip_file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($zip_file));

readfile($zip_file);
exit;
}

?>

The script creates a ZIP archive containing the files and subdirectories under the target directory and automatically starts the download in the browser.

Conclusion

Using PHP’s ZipArchive class, you can easily compress a directory and its contents into a ZIP archive. The RecursiveDirectoryIterator allows the script to include files from subdirectories while preserving their relative directory structure.

After the ZIP file is created, PHP headers and readfile() can be used to automatically send the archive to the user’s browser for download.

For large directories, make sure the server has sufficient disk space, memory, execution time, and permissions to complete the ZIP operation successfully.

FAQs

1. What is ZipArchive in PHP?

ZipArchive is a PHP class that allows applications to create, open, modify, and extract ZIP archives.

2. What PHP extension is required?

The PHP zip extension must be enabled to use the ZipArchive class.

You can check whether it is enabled with:

php -m | grep zip

3. Can this script include subdirectories?

Yes. RecursiveDirectoryIterator recursively processes the source directory and its subdirectories.

4. Will the directory structure be preserved?

Yes. The script calculates the relative path of each file and stores it in the ZIP archive, preserving the directory structure.

The HTTP headers tell the browser that the generated file should be treated as a downloadable file rather than displayed as webpage content.

Related Article

Managing Multiple PHP Versions on Ubuntu Using APT – Pheonix Solutions

How to install and configure PHP with Nginx on centos7 – Pheonix Solutions

Talk to our experts

Have a technology challenge or looking for the right solution for your business? Our team can help you with cloud, DevOps, development, infrastructure, design, and more. Feel free to reach out to our experts here.

admin

Writes about Web & Architecture at Pheonix Solutions.

Leave a Reply

Scroll to Top