{"id":1140,"date":"2017-02-21T23:07:05","date_gmt":"2017-02-21T17:37:05","guid":{"rendered":"https:\/\/pheonixsolutions.com\/blog\/?p=1140"},"modified":"2026-09-11T21:38:46","modified_gmt":"2026-09-11T16:08:46","slug":"php-zip-directory-automatically-download-using","status":"publish","type":"post","link":"https:\/\/pheonixsolutions.com\/blog\/php-zip-directory-automatically-download-using\/","title":{"rendered":"PHP: Zip a Directory and Automatically Download"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">PHP provides built-in functionality to create ZIP archives using the <code>ZipArchive<\/code> class. This can be useful when you need to allow users to download multiple files and subdirectories as a single ZIP file.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In this article, we will explain how to <strong>compress a directory, including its files and subdirectories, into a ZIP archive and automatically download the generated ZIP file using PHP<\/strong>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Before proceeding, make sure the following requirements are available:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>PHP is installed and configured on the server.<\/li>\n\n\n\n<li>The PHP <code>zip<\/code> extension is enabled.<\/li>\n\n\n\n<li>The directory that needs to be compressed exists and is accessible by the PHP process.<\/li>\n\n\n\n<li>The PHP script has permission to create the ZIP file in the specified location.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Implementation<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. Define the Source Directory and ZIP File<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Define the directory that needs to be compressed and the name of the ZIP file:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$dir = 'target';<br>$zip_file = 'file.zip';<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Here:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>$dir<\/code> specifies the directory that needs to be compressed.<\/li>\n\n\n\n<li><code>$zip_file<\/code> specifies the name of the ZIP file that will be generated and downloaded.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">2. Get the Directory Path<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use <code>realpath()<\/code> to obtain the absolute path of the source directory:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$rootPath = realpath($dir);<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This provides the actual filesystem path required by the ZIP operation.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. Initialize the ZIP Archive<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Create a new <code>ZipArchive<\/code> object and open the ZIP file:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$zip = new ZipArchive();<br><br>$zip->open($zip_file, ZipArchive::CREATE | ZipArchive::OVERWRITE);<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>CREATE<\/code> option creates the ZIP file if it does not already exist, while <code>OVERWRITE<\/code> replaces an existing ZIP file.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Find Files and Subdirectories Recursively<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use <code>RecursiveDirectoryIterator<\/code> together with <code>RecursiveIteratorIterator<\/code> to process the source directory and its subdirectories:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$files = new RecursiveIteratorIterator(<br>    new RecursiveDirectoryIterator($rootPath)<br>);<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This allows PHP to iterate through all files contained within the directory, including files located inside subdirectories.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Add Files to the ZIP Archive<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use a <code>foreach<\/code> loop to add each file to the ZIP archive:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">foreach ($files as $name => $file)<br>{<br>    if (!$file->isDir())<br>    {<br>        $filePath = $file->getRealPath();<br>        $relativePath = substr($filePath, strlen($rootPath) + 1);<br>        $zip->addFile($filePath, $relativePath);<br>    }<br>}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The script checks whether the current item is a file. If it is not a directory, the file is added to the ZIP archive.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The relative path ensures that the directory structure is maintained inside the ZIP file.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. Close the ZIP Archive<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">After all files have been added, close the ZIP archive:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$zip->close();<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">7. Download the ZIP File Automatically<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Set the appropriate HTTP headers and read the generated ZIP file:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">header('Content-Description: File Transfer');<br>header('Content-Type: application\/octet-stream');<br>header('Content-Disposition: attachment; filename=' . basename($zip_file));<br>header('Content-Transfer-Encoding: binary');<br>header('Expires: 0');<br>header('Cache-Control: must-revalidate');<br>header('Pragma: public');<br>header('Content-Length: ' . filesize($zip_file));<br><br>readfile($zip_file);<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">These headers instruct the browser to download the generated ZIP file instead of displaying it.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Complete PHP Code<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The complete PHP script is shown below:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">open($zip_file, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== TRUE) {<br>    exit('Unable to create ZIP file.');<br>}<br><br>$files = new RecursiveIteratorIterator(<br>    new RecursiveDirectoryIterator($rootPath)<br>);<br><br>foreach ($files as $name => $file) {<br>    if (!$file->isDir()) {<br>        $filePath = $file->getRealPath();<br>        $relativePath = substr($filePath, strlen($rootPath) + 1);<br><br>        $zip->addFile($filePath, $relativePath);<br>    }<br>}<br><br>$zip->close();<br><br>if (file_exists($zip_file)) {<br>    header('Content-Description: File Transfer');<br>    header('Content-Type: application\/octet-stream');<br>    header('Content-Disposition: attachment; filename=' . basename($zip_file));<br>    header('Content-Transfer-Encoding: binary');<br>    header('Expires: 0');<br>    header('Cache-Control: must-revalidate');<br>    header('Pragma: public');<br>    header('Content-Length: ' . filesize($zip_file));<br><br>    readfile($zip_file);<br>    exit;<br>}<br><br>?><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The script creates a ZIP archive containing the files and subdirectories under the <code>target<\/code> directory and automatically starts the download in the browser.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Using PHP&#8217;s <code>ZipArchive<\/code> class, you can easily compress a directory and its contents into a ZIP archive. The <code>RecursiveDirectoryIterator<\/code> allows the script to include files from subdirectories while preserving their relative directory structure.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">After the ZIP file is created, PHP headers and <code>readfile()<\/code> can be used to automatically send the archive to the user&#8217;s browser for download.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For large directories, make sure the server has sufficient disk space, memory, execution time, and permissions to complete the ZIP operation successfully.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">FAQs<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. What is <code>ZipArchive<\/code> in PHP?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><code>ZipArchive<\/code> is a PHP class that allows applications to create, open, modify, and extract ZIP archives.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. What PHP extension is required?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The PHP <code>zip<\/code> extension must be enabled to use the <code>ZipArchive<\/code> class.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can check whether it is enabled with:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">php -m | grep zip<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">3. Can this script include subdirectories?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes. <code>RecursiveDirectoryIterator<\/code> recursively processes the source directory and its subdirectories.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Will the directory structure be preserved?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes. The script calculates the relative path of each file and stores it in the ZIP archive, preserving the directory structure.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The HTTP headers tell the browser that the generated file should be treated as a downloadable file rather than displayed as webpage content.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Related Article<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/pheonixsolutions.com\/blog\/managing-multiple-php-versions-on-ubuntu-using-apt\/\">Managing Multiple PHP Versions on Ubuntu Using APT &#8211; Pheonix Solutions<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/pheonixsolutions.com\/blog\/how-to-install-and-configure-php-with-nginx-on-centos7\/\">How to install and configure PHP with Nginx on centos7 &#8211; Pheonix Solutions<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Talk to our experts<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Have a technology challenge or looking for the right solution for your business? Our team can help you with&nbsp;<strong>cloud, DevOps, development, infrastructure, design, and more<\/strong>. Feel free to reach out to our experts&nbsp;<a href=\"https:\/\/pheonixsolutions.com\/contact\">here<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction PHP provides built-in functionality to create ZIP archives using the ZipArchive class. This can be useful when you need [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":true,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[1022],"tags":[],"class_list":["post-1140","post","type-post","status-publish","format-standard","hentry","category-web-architecture","psol-cat-web-architecture"],"jetpack_publicize_connections":[],"jetpack_shortlink":"https:\/\/wp.me\/phn2x7-io","jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/1140","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/comments?post=1140"}],"version-history":[{"count":1,"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/1140\/revisions"}],"predecessor-version":[{"id":11674,"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/1140\/revisions\/11674"}],"wp:attachment":[{"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/media?parent=1140"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/categories?post=1140"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/tags?post=1140"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}