Zip a directory and automatically download using PHP

In this article we're going to look at how to zip a whole directory and then automatically start the zip file downloading using PHP. This might be useful for creating a downloadable site backup, or allowing visitors to download groups of files (e.g. photos in categories). 

The Zip Class

To start with we'll build up our zip class - lets look at the code and then break down what the methods are doing:

class zip
   private $zip;
   public function __construct( $file_name, $zip_directory)
        $this->zip = new ZipArchive();
        $this->path = dirname( __FILE__ ) . $zip_directory . $file_name . '.zip';
        $this->zip->open( $this->path, ZipArchive::CREATE );
/** * Get the absolute path to the zip file * @return string */ public function get_zip_path() { return $this->path; }
/** * Add a directory to the zip * @param $directory */ public function add_directory( $directory ) { if( is_dir( $directory ) && $handle = opendir( $directory ) ) { $this->zip->addEmptyDir( $directory ); while( ( $file = readdir( $handle ) ) !== false ) { if (!is_file($directory . '/' . $file)) { if (!in_array($file, array('.', '..'))) { $this->add_directory($directory . '/' . $file ); } } else { $this->add_file($directory . '/' . $file);
} } } }
/** * Add a single file to the zip * @param string $path */ public function add_file( $path ) { $this->zip->addFile( $path, $path); }
/** * Close the zip file */ public function save() { $this->zip->close(); } }

The Construct

The construct takes in two parameters, the filename for the final zip and the directory we want to store it in.  Using PHP's ZipArchive we then create and open the zip file. 

Get Zip Path

The get_zip_path method allows us to return the full path to the downloadable zip, we'll use this later for the download code. 

Adding the directory

Next we create an add_directory method to pass in the folder that we want to zip. In this method we create an open directory handle to iterate through the directory subfolders and files. We check if the current iteration is for a folder (in which case re-call the same method to continue iteration), or for a file, in which case call the add_file method to actually add this to the zip. 

Notice also that we use 'addEmptyDirectory' to replicate the same folder structure - you can take this out if you don't want empty directories as the 'add_file' method will automatically do this. Also notice that we check for '.' and '..' that references the current and next level folder - we want to ignore these.

Add file

Now we create the method 'add_file' that will actually add the file to the zip. This is called from the add_directory method but can also be called directly so we make this function public. To add the file we use ZipArchive's addFile function. 

Close the Zip

Lastly we need to close the zip file, this has been placed in a 'save' function.

Creating a Zip File

Now we've got the class we can create a zip file like so:

$zip_name = 'zip_' . time();
$zip_directory = '/';
$zip = new zip( $zip_name, $zip_directory );
$zip->add_directory( 'files' );

Auto Download the file

To start the zip file auto-downloading we get the zip path from the zip class, set the page headers and then use 'readfile' to output the contents of the zip.

$zip_path = $zip->get_zip_path();
header( "Pragma: public" ); header( "Expires: 0" ); header( "Cache-Control: must-revalidate, post-check=0, pre-check=0" ); header( "Cache-Control: public" ); header( "Content-Description: File Transfer" ); header( "Content-type: application/zip" ); header( "Content-Disposition: attachment; filename=\"" . $zip_name . "\"" ); header( "Content-Transfer-Encoding: binary" ); header( "Content-Length: " . filesize( $zip_path ) ); readfile( $zip_path );

If you're using this script for something like site backups you'll need to add some additional security such as htaccess or hiding the page behind a password protected area to ensure it's not publicly accessible. 

Sign Up

NEXT: Build an HTML5 responsive contact form

In this tutorial we'll be using the latest HTML5 form attributes with modern CSS responsive techniques to create a flexible, cross-platform contact form.

comments powered by Disqus

Popular Tags

Need a web developer?

If you'd like to work with code synthesis on your next project get in touch via the contact page.