Categories
PHP

ZipArchive – Zip and Unzip Files and Folders

Let’s create a compressed Zip archive in PHP with ZipArchive class, which provides many features for reading and writing Zip archives.

Example: Zip Multiple Files

<?php
 $zip = new ZipArchive();

 $open = $zip->open('file.zip', ZIPARCHIVE::CREATE | ZipArchive::OVERWRITE);
 if ($open !== TRUE)
  die ('Error: Could not create archive');

 //Add file to archive
 $zip->addFile('D:/uploads/abc.txt', 'abc.txt');

 //Add file to archive in img folder
 $zip->addFile('D:/uploads/img/dog.jpg', 'img/dog.jpg');
 $zip->addFile('D:/uploads/img/image.jpg', 'img/image.jpg');
 //$total = $zip->numFiles;
 $total = $zip->count();
 $zip->close();
 
 echo "Archive created successfully. Total files: $total";
 //Archive created successfully. Total files: 3

After creating a new instance of the ZipArchive class, the open() method is used to create a new (or to open an existing) zip archive for reading, writing, or modifying.

The first parameter of the open() method is the file name of the ZIP archive to open and the second parameter contains flags. The ZIPARCHIVE::CREATE flag creates the archive if it does not exist and the ZipArchive::OVERWRITE flag empties the archive if it already exists.

The addFile() method is then used to add files to the zip file. The first parameter of this method is the path to the file to add and the second parameter is the local name of the file inside the ZIP archive. You can add files in different folders by separating the folder name and filename with a forward slash, for example, to add image.jpg file in img folder in the archive write img/image.jpg in the second parameter:

$zip->addFile('/path/a/b/image.jpg', 'img/image.jpg'); 

The close() method is used to compress files and write the zip file to the disk.

Zip All Files in a Directory (Folder)

The following code will zip (compress) all files in the given path:

<?php
 //Compressing all files in the "uploads" folder
 $dir = realpath('uploads');
 $zip = new ZipArchive();

 $open = $zip->open('file.zip', ZIPARCHIVE::CREATE | ZipArchive::OVERWRITE);
 if ($open !== TRUE)
  die ('Error: Could not create archive');

 $files = scandir( $dir );
 foreach ($files as $fileName) {
  $realPath = $dir.DIRECTORY_SEPARATOR.$fileName;
  if (is_file($realPath)) {
   $zip->addFile($realPath, $fileName);
  }
 }
 //$total = $zip->numFiles;
 $total = $zip->count();
 $zip->close();

 echo 'Archive created successfully.<br>';
 echo "Total files; $total";
 //Archive created successfully.
 //Total files; 4

Zip Entire Directory (Folder) Recursively

The following example demonstrates how to compress a directory recursively (all files and sub-folders) by using the ZipArchive, RecursiveIteratorIterator and RecursiveDirectoryIterator classes:

<?php
 $dir = realpath('uploads');
 $zipName = 'file.zip';
 
 $zip = new ZipArchive();
 $zip->open($zipName, ZipArchive::CREATE | ZipArchive::OVERWRITE);
 
 $files = new RecursiveIteratorIterator(
  new RecursiveDirectoryIterator($dir)
  );

 foreach ($files as $name => $file){
  if (!$file->isDir()) {
   $filePath = $file->getRealPath();
   $relativePath = substr($filePath, strlen($dir) + 1);
   
   //Fixing path bug on Windows OS
   if (DIRECTORY_SEPARATOR === '\\')
    $relativePath = str_replace('\\', '/', $relativePath);

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

 echo 'done...<br>';
 $zip->close();

Unzip: Extract the archive contents

Extract the complete archive or the given files to the specified destination.

Unzip an archive:

<?php
 $zip = new ZipArchive();
 $open = $zip->open('file.zip');
 if ($open !== TRUE)
  die ('Error: Unable to open archive');
 $zip->extractTo('data/files');
 //$total = $zip->numFiles;
 $total = $zip->count();
 $zip->close();

 echo "$total files extracted";
 // 3 files extracted

Unzip one or more files from an archive:

<?php
 ...
 //Extract single entry
 $zip->extractTo('data/files', 'img/404.css');

 //Use array to extract multiple entries
 $entries = ['abc.txt', 'img/404.css'];
 $zip->extractTo('data/files', $entries);
 ...

The second parameter of extractTo() method accepts a string or array, specify the name of an entry or an array of names to extract a single or multiple files from an archive:

<?php
 $zip = new ZipArchive();
 $open = $zip->open('file.zip');
 if ($open !== TRUE)
  die ('Error: Unable to open archive');
 $zip->extractTo('data/files', ['img/404.css','abc.txt']);
 $zip->close();

Working with Files in PHP: