How to zip a whole folder using PHP

PhpZip

Php Problem Overview


I have found here at stackoveflow some codes on how to ZIP a specific file, but how about a specific folder?

Folder/
  index.html
  picture.jpg
  important.txt

inside in My Folder, there are files. after zipping the My Folder, i also want to delete the whole content of the folder except important.txt.

Found this here at stack

I need your help. thanks.

Php Solutions


Solution 1 - Php

Code updated 2015/04/22.

Zip a whole folder:

// Get real path for our folder
$rootPath = realpath('folder-to-zip');

// Initialize archive object
$zip = new ZipArchive();
$zip->open('file.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE);

// Create recursive directory iterator
/** @var SplFileInfo[] $files */
$files = new RecursiveIteratorIterator(
	new RecursiveDirectoryIterator($rootPath),
	RecursiveIteratorIterator::LEAVES_ONLY
);

foreach ($files as $name => $file)
{
	// Skip directories (they would be added automatically)
	if (!$file->isDir())
	{
		// Get real and relative path for current file
		$filePath = $file->getRealPath();
		$relativePath = substr($filePath, strlen($rootPath) + 1);

		// Add current file to archive
		$zip->addFile($filePath, $relativePath);
	}
}

// Zip archive will be created only after closing object
$zip->close();

Zip a whole folder + delete all files except "important.txt":

// Get real path for our folder
$rootPath = realpath('folder-to-zip');

// Initialize archive object
$zip = new ZipArchive();
$zip->open('file.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE);

// Initialize empty "delete list"
$filesToDelete = array();

// Create recursive directory iterator
/** @var SplFileInfo[] $files */
$files = new RecursiveIteratorIterator(
	new RecursiveDirectoryIterator($rootPath),
	RecursiveIteratorIterator::LEAVES_ONLY
);

foreach ($files as $name => $file)
{
	// Skip directories (they would be added automatically)
	if (!$file->isDir())
	{
		// Get real and relative path for current file
		$filePath = $file->getRealPath();
		$relativePath = substr($filePath, strlen($rootPath) + 1);

		// Add current file to archive
		$zip->addFile($filePath, $relativePath);

		// Add current file to "delete list"
        // delete it later cause ZipArchive create archive only after calling close function and ZipArchive lock files until archive created)
		if ($file->getFilename() != 'important.txt')
		{
			$filesToDelete[] = $filePath;
		}
	}
}

// Zip archive will be created only after closing object
$zip->close();

// Delete all files from "delete list"
foreach ($filesToDelete as $file)
{
	unlink($file);
}

Solution 2 - Php

There is a useful undocumented method in the ZipArchive class: addGlob();

$zipFile = "./testZip.zip";
$zipArchive = new ZipArchive();

if ($zipArchive->open($zipFile, (ZipArchive::CREATE | ZipArchive::OVERWRITE)) !== true)
	die("Failed to create archive\n");

$zipArchive->addGlob("./*.txt");
if ($zipArchive->status != ZIPARCHIVE::ER_OK)
	echo "Failed to write files to zip\n";

$zipArchive->close();

Now documented at: www.php.net/manual/en/ziparchive.addglob.php

Solution 3 - Php

Try this:

$zip = new ZipArchive;
$zip->open('myzip.zip', ZipArchive::CREATE);
foreach (glob("target_folder/*") as $file) {
    $zip->addFile($file);
    if ($file != 'target_folder/important.txt') unlink($file);
}
$zip->close();

This will not zip recursively though.

Solution 4 - Php

I assume this is running on a server where the zip application is in the search path. Should be true for all unix-based and I guess most windows-based servers.

exec('zip -r archive.zip "My folder"');
unlink('My\ folder/index.html');
unlink('My\ folder/picture.jpg');

The archive will reside in archive.zip afterwards. Keep in mind that blanks in file or folder names are a common cause of errors and should be avoided where possible.

Solution 5 - Php

I tried with the code below and it is working. The code is self explanatory, please let me know if you have any questions.

<?php
class FlxZipArchive extends ZipArchive 
{
 public function addDir($location, $name) 
 {
       $this->addEmptyDir($name);
       $this->addDirDo($location, $name);
 } 
 private function addDirDo($location, $name) 
 {
    $name .= '/';
    $location .= '/';
    $dir = opendir ($location);
    while ($file = readdir($dir))
    {
        if ($file == '.' || $file == '..') continue;
        $do = (filetype( $location . $file) == 'dir') ? 'addDir' : 'addFile';
        $this->$do($location . $file, $name . $file);
    }
 } 
}
?>

<?php
$the_folder = '/path/to/folder/to/be/zipped';
$zip_file_name = '/path/to/zip/archive.zip';
$za = new FlxZipArchive;
$res = $za->open($zip_file_name, ZipArchive::CREATE);
if($res === TRUE) 
{
    $za->addDir($the_folder, basename($the_folder));
    $za->close();
}
else{
echo 'Could not create a zip archive';
}
?>

Solution 6 - Php

This is a function that zips a whole folder and its contents in to a zip file and you can use it simple like this :

addzip ("path/folder/" , "/path2/folder.zip" );

function :

// compress all files in the source directory to destination directory 
    function create_zip($files = array(), $dest = '', $overwrite = false) {
	if (file_exists($dest) && !$overwrite) {
		return false;
	}
	if (($files)) {
		$zip = new ZipArchive();
		if ($zip->open($dest, $overwrite ? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE) !== true) {
			return false;
		}
		foreach ($files as $file) {
			$zip->addFile($file, $file);
		}
		$zip->close();
		return file_exists($dest);
	} else {
		return false;
	}
}

function addzip($source, $destination) {
	$files_to_zip = glob($source . '/*');
	create_zip($files_to_zip, $destination);
	echo "done";
}

Solution 7 - Php

Use this function:

function zip($source, $destination)
{
    if (!extension_loaded('zip') || !file_exists($source)) {
        return false;
    }

    $zip = new ZipArchive();
    if (!$zip->open($destination, ZIPARCHIVE::CREATE)) {
        return false;
    }

    $source = str_replace('\\', '/', realpath($source));

    if (is_dir($source) === true) {
        $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);

        foreach ($files as $file) {
            $file = str_replace('\\', '/', $file);

            // Ignore "." and ".." folders
            if (in_array(substr($file, strrpos($file, '/')+1), array('.', '..'))) {
				continue;
			}               

            $file = realpath($file);

            if (is_dir($file) === true) {
                $zip->addEmptyDir(str_replace($source . '/', '', $file . '/'));
            } elseif (is_file($file) === true) {
                $zip->addFromString(str_replace($source . '/', '', $file), file_get_contents($file));
            }
        }
    } elseif (is_file($source) === true) {
        $zip->addFromString(basename($source), file_get_contents($source));
    }

    return $zip->close();
}

Example use:

zip('/folder/to/compress/', './compressed.zip');

Solution 8 - Php

Why not Try EFS PhP-ZiP MultiVolume Script ... I zipped and transferred hundreds of gigs and millions of files ... ssh is needed to effectively create archives.

But i belive that resulting files can be used with exec directly from php:

exec('zip -r backup-2013-03-30_0 . -i@backup-2013-03-30_0.txt');

I do not know if it works. I have not tried ...

"the secret" is that the execution time for archiving should not exceed the time allowed for execution of PHP code.

Solution 9 - Php

This is a working example of making ZIPs in PHP:

$zip = new ZipArchive();
$zip_name = time().".zip"; // Zip name
$zip->open($zip_name,  ZipArchive::CREATE);
foreach ($files as $file) {
  echo $path = "uploadpdf/".$file;
  if(file_exists($path)){
  $zip->addFromString(basename($path),  file_get_contents($path));---This is main function  
  }
  else{
   echo"file does not exist";
  }
}
$zip->close();

Solution 10 - Php

This will resolve your issue. Please try it.

$zip = new ZipArchive;
$zip->open('testPDFZip.zip', ZipArchive::CREATE);
foreach (glob(APPLICATION_PATH."pages/recruitment/uploads/test_pdf_folder/*") as $file) {
	$new_filename = end(explode("/",$file));
	$zip->addFile($file,"emp/".$new_filename);
}			
$zip->close();

Solution 11 - Php

I found this post in google as the second top result, first was using exec :(

Anyway, while this did not suite my needs exactly.. I decided to post an answer for others with my quick but extended version of this.

SCRIPT FEATURES

  • Backup file naming day by day, PREFIX-YYYY-MM-DD-POSTFIX.EXTENSION
  • File Reporting / Missing
  • Previous Backups Listing
  • Does not zip / include previous backups ;)
  • Works on windows/linux

Anyway, onto the script.. While it may look like a lot.. Remember there is excess in here.. So feel free to delete the reporting sections as needed...

Also it may look messy as well and certain things could be cleaned up easily... So dont comment about it, its just a quick script with basic comments thrown in.. NOT FOR LIVE USE.. But easy to clean up for live use!

In this example, it is run from a directory that is inside of the root www / public_html folder.. So only needs to travel up one folder to get to the root.

<?php
	// DIRECTORY WE WANT TO BACKUP
	$pathBase = '../';	// Relate Path

	// ZIP FILE NAMING ... This currently is equal to = sitename_www_YYYY_MM_DD_backup.zip 
	$zipPREFIX = "sitename_www";
	$zipDATING = '_' . date('Y_m_d') . '_';
	$zipPOSTFIX = "backup";
	$zipEXTENSION = ".zip";

	// SHOW PHP ERRORS... REMOVE/CHANGE FOR LIVE USE
	ini_set('display_errors',1);
	ini_set('display_startup_errors',1);
	error_reporting(-1);




// ############################################################################################################################
// 									NO CHANGES NEEDED FROM THIS POINT
// ############################################################################################################################

	// SOME BASE VARIABLES WE MIGHT NEED
	$iBaseLen = strlen($pathBase);
	$iPreLen = strlen($zipPREFIX);
	$iPostLen = strlen($zipPOSTFIX);
	$sFileZip = $pathBase . $zipPREFIX . $zipDATING . $zipPOSTFIX . $zipEXTENSION;
	$oFiles = array();
	$oFiles_Error = array();
	$oFiles_Previous = array();
	
	// SIMPLE HEADER ;)
	echo '<center><h2>PHP Example: ZipArchive - Mayhem</h2></center>';

	// CHECK IF BACKUP ALREADY DONE
	if (file_exists($sFileZip)) {
		// IF BACKUP EXISTS... SHOW MESSAGE AND THATS IT
		echo "<h3 style='margin-bottom:0px;'>Backup Already Exists</h3><div style='width:800px; border:1px solid #000;'>";
			echo '<b>File Name: </b>',$sFileZip,'<br />';
			echo '<b>File Size: </b>',$sFileZip,'<br />';
		echo "</div>";
		exit; // No point loading our function below ;)
	} else {
		
		// NO BACKUP FOR TODAY.. SO START IT AND SHOW SCRIPT SETTINGS
		echo "<h3 style='margin-bottom:0px;'>Script Settings</h3><div style='width:800px; border:1px solid #000;'>";
			echo '<b>Backup Directory: </b>',$pathBase,'<br /> ';
			echo '<b>Backup Save File: </b>',$sFileZip,'<br />';
		echo "</div>";
		
		// CREATE ZIPPER AND LOOP DIRECTORY FOR SUB STUFF
		$oZip = new ZipArchive;
		$oZip->open($sFileZip,  ZipArchive::CREATE | ZipArchive::OVERWRITE);
		$oFilesWrk = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($pathBase),RecursiveIteratorIterator::LEAVES_ONLY);
		foreach ($oFilesWrk as $oKey => $eFileWrk) {
			// VARIOUS NAMING FORMATS OF THE CURRENT FILE / DIRECTORY.. RELATE & ABSOLUTE
			$sFilePath = substr($eFileWrk->getPathname(),$iBaseLen, strlen($eFileWrk->getPathname())- $iBaseLen);
			$sFileReal = $eFileWrk->getRealPath();
			$sFile = $eFileWrk->getBasename();

			// WINDOWS CORRECT SLASHES
			$sMyFP = str_replace('\\', '/', $sFileReal);
			
			if (file_exists($sMyFP)) {	// CHECK IF THE FILE WE ARE LOOPING EXISTS
				if ($sFile!="."  && $sFile!="..") {	// MAKE SURE NOT DIRECTORY / . || ..
					// CHECK IF FILE HAS BACKUP NAME PREFIX/POSTFIX... If So, Dont Add It,, List It
					if (substr($sFile,0, $iPreLen)!=$zipPREFIX && substr($sFile,-1, $iPostLen + 4)!= $zipPOSTFIX.$zipEXTENSION) {
						$oFiles[] = $sMyFP;						// LIST FILE AS DONE
						$oZip->addFile($sMyFP, $sFilePath);		// APPEND TO THE ZIP FILE
					} else {
						$oFiles_Previous[] = $sMyFP; 			// LIST PREVIOUS BACKUP
					}
				}
			} else {
				$oFiles_Error[] = $sMyFP; 						// LIST FILE THAT DOES NOT EXIST
			}
		}
		$sZipStatus = $oZip->getStatusString();					// GET ZIP STATUS
		$oZip->close();	// WARNING: Close Required to append files, dont delete any files before this.

		// SHOW BACKUP STATUS / FILE INFO
		echo "<h3 style='margin-bottom:0px;'>Backup Stats</h3><div style='width:800px; height:120px; border:1px solid #000;'>";
			echo "<b>Zipper Status: </b>" . $sZipStatus . "<br />";
			echo "<b>Finished Zip Script: </b>",$sFileZip,"<br />";
			echo "<b>Zip Size: </b>",human_filesize($sFileZip),"<br />";
		echo "</div>";
		
		
		// SHOW ANY PREVIOUS BACKUP FILES
		echo "<h3 style='margin-bottom:0px;'>Previous Backups Count(" . count($oFiles_Previous) . ")</h3><div style='overflow:auto; width:800px; height:120px; border:1px solid #000;'>";
		foreach ($oFiles_Previous as $eFile) {
			echo basename($eFile) . ", Size: " . human_filesize($eFile) . "<br />";
		}
		echo "</div>";

		// SHOW ANY FILES THAT DID NOT EXIST??
		if (count($oFiles_Error)>0) {
			echo "<h3 style='margin-bottom:0px;'>Error Files, Count(" . count($oFiles_Error) . ")</h3><div style='overflow:auto; width:800px; height:120px; border:1px solid #000;'>";
			foreach ($oFiles_Error as $eFile) {
				echo $eFile . "<br />";
			}
			echo "</div>";
		}
		
		// SHOW ANY FILES THAT HAVE BEEN ADDED TO THE ZIP
		echo "<h3 style='margin-bottom:0px;'>Added Files, Count(" . count($oFiles) . ")</h3><div style='overflow:auto; width:800px; height:120px; border:1px solid #000;'>";
		foreach ($oFiles as $eFile) {
			echo $eFile . "<br />";
		}
		echo "</div>";

	}

	
	// CONVERT FILENAME INTO A FILESIZE AS Bytes/Kilobytes/Megabytes,Giga,Tera,Peta
	function human_filesize($sFile, $decimals = 2) {
		$bytes = filesize($sFile);
		$sz = 'BKMGTP';
		$factor = floor((strlen($bytes) - 1) / 3);
		return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . @$sz[$factor];
	}
?>

WHAT DOES IT DO??

It will simply zip the complete contents of the variable $pathBase and store the zip in that same folder. It does a simple detection for previous backups and skips them.

CRON BACKUP

This script i've just tested on linux and worked fine from a cron job with using an absolute url for the pathBase.

Solution 12 - Php

Use this is working fine.

$dir = '/Folder/';
$zip = new ZipArchive();
$res = $zip->open(trim($dir, "/") . '.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE);
if ($res === TRUE) {
    foreach (glob($dir . '*') as $file) {
        $zip->addFile($file, basename($file));
    }
    $zip->close();
} else {
    echo 'Failed to create to zip. Error: ' . $res;
}

Solution 13 - Php

Create a zip folder in PHP.

Zip create method

   public function zip_creation($source, $destination){
    $dir = opendir($source);
    $result = ($dir === false ? false : true);

    if ($result !== false) {

        
        $rootPath = realpath($source);
         
        // Initialize archive object
        $zip = new ZipArchive();
        $zipfilename = $destination.".zip";
        $zip->open($zipfilename, ZipArchive::CREATE | ZipArchive::OVERWRITE );
         
        // Create recursive directory iterator
        /** @var SplFileInfo[] $files */
        $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($rootPath), RecursiveIteratorIterator::LEAVES_ONLY);
         
        foreach ($files as $name => $file)
        {
            // Skip directories (they would be added automatically)
            if (!$file->isDir())
            {
                // Get real and relative path for current file
                $filePath = $file->getRealPath();
                $relativePath = substr($filePath, strlen($rootPath) + 1);
         
                // Add current file to archive
                $zip->addFile($filePath, $relativePath);
            }
        }
         
        // Zip archive will be created only after closing object
        $zip->close();
        
        return TRUE;
    } else {
        return FALSE;
    }


}

Call the zip method

$source = $source_directory;
$destination = $destination_directory;
$zipcreation = $this->zip_creation($source, $destination);

Solution 14 - Php

If you have subfolders and you want to preserve the structure of the folder do this:

$zip = new \ZipArchive();
$fileName = "my-package.zip";
if ($zip->open(public_path($fileName), \ZipArchive::CREATE) === true)
{
	$files = \Illuminate\Support\Facades\File::allFiles(
		public_path('/MY_FOLDER_PATH/')
	);

	foreach ($files as $file) {
		$zip->addFile($file->getPathname(), $file->getRelativePathname());
	}

	$zip->close();
	return response()
		->download(public_path($fileName))
		->deleteFileAfterSend(true);
}

deleteFileAfterSend(true) to delete the file my-package.zip from the server.

Don't forget to change /MY_FOLDER_PATH/ with the path of your folder that you want to download.

Solution 15 - Php

I did some small improvement in the script.

  <?php
    $directory = "./";
    //create zip object
    $zip = new ZipArchive();
    $zip_name = time().".zip";
    $zip->open($zip_name,  ZipArchive::CREATE);
    $files = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($directory),
        RecursiveIteratorIterator::LEAVES_ONLY
    );
    foreach ($files as $file) {
        $path = $file->getRealPath();
        //check file permission
        if(fileperms($path)!="16895"){
            $zip->addFromString(basename($path),  file_get_contents($path)) ;
            echo "<span style='color:green;'>{$path} is added to zip file.<br /></span> " ;
        }
        else{
            echo"<span style='color:red;'>{$path} location could not be added to zip<br /></span>";
        }
    }
    $zip->close();
    ?>

Solution 16 - Php

For anyone reading this post and looking for a why to zip the files using addFile instead of addFromString, that does not zip the files with their absolute path (just zips the files and nothing else), see my question and answer here

Solution 17 - Php

includes all sub-folders:

new GoodZipArchive('path/to/input/folder',    'path/to/output_zip_file.zip') ;

Here is source-code (there might have been an update, but below I put the copy of that code):

class GoodZipArchive extends ZipArchive 
{
	public function __construct($a=false, $b=false) { $this->create_func($a, $b);  }
	
	public function create_func($input_folder=false, $output_zip_file=false)
	{
		if($input_folder !== false && $output_zip_file !== false)
		{
			$res = $this->open($output_zip_file, ZipArchive::CREATE);
			if($res === TRUE) 	{ $this->addDir($input_folder, basename($input_folder)); $this->close(); }
			else  				{ echo 'Could not create a zip archive. Contact Admin.'; }
		}
	}
	
    // Add a Dir with Files and Subdirs to the archive
    public function addDir($location, $name) {
        $this->addEmptyDir($name);
        $this->addDirDo($location, $name);
    }

    // Add Files & Dirs to archive 
    private function addDirDo($location, $name) {
        $name .= '/';         $location .= '/';
        // Read all Files in Dir
        $dir = opendir ($location);
        while ($file = readdir($dir))    {
            if ($file == '.' || $file == '..') continue;
          // Rekursiv, If dir: GoodZipArchive::addDir(), else ::File();
            $do = (filetype( $location . $file) == 'dir') ? 'addDir' : 'addFile';
            $this->$do($location . $file, $name . $file);
        }
    } 
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionwoninanaView Question on Stackoverflow
Solution 1 - PhpDadorView Answer on Stackoverflow
Solution 2 - PhpMark BakerView Answer on Stackoverflow
Solution 3 - PhpnetcoderView Answer on Stackoverflow
Solution 4 - PhpKevin ReadView Answer on Stackoverflow
Solution 5 - PhpAmir Md AmiruzzamanView Answer on Stackoverflow
Solution 6 - PhpAlireza FallahView Answer on Stackoverflow
Solution 7 - PhpWaqar AlamgirView Answer on Stackoverflow
Solution 8 - PhpByREVView Answer on Stackoverflow
Solution 9 - PhpSun LoveView Answer on Stackoverflow
Solution 10 - PhpLakhanView Answer on Stackoverflow
Solution 11 - PhpAngry 84View Answer on Stackoverflow
Solution 12 - PhpIndrajeet SinghView Answer on Stackoverflow
Solution 13 - PhpMamun SabujView Answer on Stackoverflow
Solution 14 - PhpHatim LagzarView Answer on Stackoverflow
Solution 15 - PhpPoohspearView Answer on Stackoverflow
Solution 16 - PhpSkytigerView Answer on Stackoverflow
Solution 17 - PhpT.ToduaView Answer on Stackoverflow