skip to content

PHP: Listing files in a ZIP archive

Have you ever wanted to be able to look inside a zip archive using PHP to see what is in there without having to first unzip the file? Here we present a standalone static PHP class that does just that.

ZipArchiveBrowser source code

Here is the complete source code for \Chirp\ZipArchiveBrowser:

<?PHP namespace Chirp; class ZipArchiveBrowser { // Original PHP code by Chirp Internet: www.chirpinternet.eu // Please acknowledge use of this code by including this header. private static $files = []; // file tree private static function add_directory(&$base, $parts) { // add an empty directory to the tree $dir = array_shift($parts); if(!isset($base[$dir])) { $base[$dir] = []; } if(isset($parts[0]) && $parts[0]) { self::add_directory($base[$dir], $parts); } } private static function add_file(&$base, $parts) { // add a file to the tree if(isset($parts[1]) && $parts[1]) { self::add_file($base[array_shift($parts)], $parts); } else { $base[] = end($parts); } } public static function get_contents($inputfile, $include_empty_dirs = TRUE) { if(!file_exists($inputfile)) { throw new \Exception("File Not Found."); return FALSE; } // open zip file using ZipArchive $zip = new \ZipArchive; if(TRUE === ($ret = $zip->open($inputfile, \ZipArchive::RDONLY))) { $numfiles = $zip->count(); for($idx=0; $idx < $numfiles; $idx++) { $parts = explode(DIRECTORY_SEPARATOR, $zip->getNameIndex($idx)); if(end($parts)) { // found a file self::add_file(self::$files, $parts); } elseif($include_empty_dirs) { // found an empty directory self::add_directory(self::$files, $parts); } } // for each entry in zip file $zip->close(); } else { throw new \Exception("File could not be opened by ZipArchive.", $ret); return FALSE; } return self::$files; } }

expand code box

There is a single public method get_contents() which will return a file tree describing the zip archive contents as an array. It has a flag to let you exclude empty directories. By default empty directories will be included in the output.

The add_* methods operate recursively by passing down the current branch (position in the tree) that is being constructed.

Using ZipArchiveBrowser

Using the ZipArchiveBrowser class is straight-forward:

<?PHP $inputfile = "path-to-your-zip-file.zip" try { $output = \Chirp\ZipArchiveBrowser::get_contents($inputfile); echo "<pre>",print_r($output),"</pre>\n"; } catch(\Exception $e) { echo "Caught exception: (",$e->getCode(),") ",$e->getMessage(),"\n"; } ?>

Note that because this is a static class you don't have to instantiate an object using new, but can instead invoke the public method directly using ::.

THe class will throw an Exception in the case of a missing file or one that can't be opened by ZipArchive. In the latter case there will be an error code that can be looked up here. For example, ZipArchive::ER_NOZIP (19) means 'Not a zip archive'.

Sample output

For a simple zip archive with no directories:

Array ( [0] => Style Guide.pdf [1] => Logo.png [2] => Logo.eps [3] => logo.jpg )

For a more complicated folder structure:

Array ( [Random Images] => Array ( [0] => background4.jpg [1] => background5.jpg [2] => background7.jpg [3] => maze-builder-4.png [4] => background6.jpg [5] => balloon-orange.png [6] => background2.jpg [7] => .DS_Store [8] => maze-builder-1.png [9] => background3.jpg [10] => background1.jpg [11] => maze-builder-3.png [12] => maze-builder-2.png [13] => balloon-blue.png [14] => background10.jpg [15] => background11.jpg [empty folder] => Array ( ) [16] => balloon.png [another folder] => Array ( [yet another folder] => Array ( [0] => background12.jpg ) [0] => .DS_Store ) ) )

The input needs to be a local file that is readable by the web server. In practice this may be a user-uploaded file or one that has been fetched from a third-party API. The ZIP file is not actually unpacked by this script - it just has its index read.

To have the files listed alphabetically you can just use asort($output) in the above code. For more advanced sorting options see our article on Directory Listing using SPL where we demonstrate how to use the SplHeap PHP class.

An HTML form for uploading

To get you started, here is an HTML form you can use to allow a ZIP file to be uploaded for processing:

<form method="POST" action="#" enctype="multipart/form-data"> <p>Zip File: <input type="file" required name="zipfile" accept="application/zip"></p> <p><input type="submit" name="upload" value="Upload"></p> </form>

Note that the 'enctype' form attribute is required if you want the file to be uploaded, while the 'accept' attribute on the file input is advisory only and will not actually prevent uploading of other file types by the browser.

You can then get the location of the uploaded (temporary) file using:

<?PHP $inputfile = $_FILES['zipfile']['tmp_name']; ?>

Please be careful allowing users to upload files to your server!

Future developments

The above script, while useful, is just a first step towards a system that we are developing that will allow in-place editing of the ZIP archive contents to delete and rename files and then re-save the file. Stay tuned for details.

References

< PHP

Post your comment or question
top