How to zip a whole folder using PHP
Asked Answered
S

20

179

I have found here at stackoveflow some code 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

Stillas answered 6/2, 2011 at 16:59 Comment(5)
As far as I can see, the stackoverflow link you have provided actually does zip multiple files. Which part do you have trouble with?Unprepared
@lasseespeholt The link i have given you zips only a specific file, not the folder and the content of the folder..Stillas
He takes an array of files (essentially a folder) and adds all the files to the zip file (the loop). I can see a fine answer have been posted now +1 :) which is the same code, the array is just a list of files from a directory now.Unprepared
possible duplicate of compress/archive folder using php scriptAbseil
This can help you codingbin.com/compressing-a-directory-of-files-with-phpNightie
A
425

Zip a whole folder:

// Remove any trailing slashes from the path
$rootPath = rtrim($rootPath, '\\/');

// 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 $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":

// Remove any trailing slashes from the path
$rootPath = rtrim($rootPath, '\\/');

// 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 $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);
}
Admetus answered 6/2, 2011 at 17:10 Comment(22)
This is almost correct. Adding the file to the may silently fail due to reaching a file descriptor limit. the php.net page for ZipArchive has some workarounds, however.Eneidaenema
It deletes the some file on My folder, I can't find the created .zip folder and there some folders to inside My folder that can't be deleted.Stillas
You must set chmod (writable) on dir (where located this script) to 777. For example: If script located in /var/www/localhost/script.php, then you need set chmod 0777 on dir /var/www/localhost/.Admetus
Deleting the files before calling $zip->close() will not work. Check my answer hereEssex
before adding the files to zip it is good to check if it is not a directory ising is_dir() function.Arrowwood
Please give me a reply. zip file is created successfully but when i will try to extract it then it is showing error. So please suggest me changes in the code.Funereal
@alnassre that's requirement from the question: "i also want to delete the whole content of the folder except important.txt". Also I advice you to always read code before execute it.Admetus
Great script. Just a question though, anyway to get the percent of completion? Also, possible to modify compression levels?Inexact
@nick-newman, yeah, to calculate percent you can use php.net/manual/ru/function.iterator-count.php + counter inside loop. Regarding compression level - it's not possible with ZipArchive at this moment: #1833668Admetus
How do you force download using the "download" attribute after the ZIP is created?Breathing
As of 2017: The first part of this answer is failing (I didn't tryed the second one). I got a ZipArchive::close(): It is not safe to rely on the system's timezone settings.... and a Fatal error: Maximum execution time of 30 seconds exceeded. Just to let you know.Denysedenzil
@louys-patrice-bessette both problems is not about code in the answer being wrong, but about your settings. You should select timezone (either in php.ini or in your config), see that answer https://mcmap.net/q/137964/-php-warning-date-it-is-not-safe-to-rely-on-the-system-39-s-timezone-settings-os-x And the second problem happens because you have time limit for script execution, see that answer https://mcmap.net/q/137965/-maximum-execution-time-of-30-seconds-exceededAdmetus
@Admetus when i download this it downloads zip to the projects public folder.i wants it at the download folder of pc.how can i do thisCarapace
@colombo, this code only creates the zip archive. If you want to send it to user (so it will be downloaded in browser) you need either redirect user to created archive (i.e. to /file.zip, see https://mcmap.net/q/45190/-how-do-i-make-a-redirect-in-php for example) or send it directly to user (see https://mcmap.net/q/137966/-send-zip-file-to-browser-force-direct-download for example).Admetus
If you are testing on MacOS and using a temp file, then getRealPath will return /private/var while getPathname returns /var, the substr would give unexpected results.Selfpronouncing
Hello, its 2019 but your answer is still watched. How about delete from the created zip one folder (and its contents, off course)? I mean, I need to backup everything on my folder except a specific one. I'm trying with if ($file -> isDir()) { $filesToDelete[] = $file -> getFilename(); } but all I've got is . and .., (hiden files within the folder I want to skip) Thanks!Lamoureux
@Pluda, try using RecursiveIteratorIterator::CHILD_FIRST instead of RecursiveIteratorIterator::LEAVES_ONLY (see docs here php.net/manual/en/recursiveiteratoriterator.construct.php). Also, in order to delete the directory you have to delete it's content first. So besides adding directory itself to $filesToDelete it's also necessary to add all files in that directory to $filesToDelete.Admetus
@Admetus Thanks! I'm trying to avoid adding the folder to the zip, but I'm not getting there. Something like if isDir and dirName is "myFolder" skip iteration in myFolder and continue with the rest... Maybe I'm complicating things...Lamoureux
@Pluda, ah, sorry, seems like I misunderstood you at first. Then you need to check if $relativePath starts with $dirToExclude, like this: if (substr($relativePath, 0, strlen($dirToExclude)) == $dirToExclude) { continue; } (note that it could give wrong results in case of symlinks)Admetus
@Dador, thanks! I was able to delete the folder after $zip -> close, but for me that doesn't make logic. Why add something and 1 millisecond after remove it? Now with your help it is possible to suppress the folder before closing the zip. Haven't noticed wrong results so far. Thanks a ton!Lamoureux
I could not use this approach to add the files under a Junction in Windows (symlink), it stops iterating inside the junction if it is outside the initial $rootPath, however it shows me the target directory, and then I can start a new RecursiveDirectoryIterator from that, but I cannot know which was the junction/symlink to put under such directory structure. If ./imasymlink points to /other/thing, I get /other/thing, but I don't get iamsymlink to put /other/thing/* under /imasymlink/ The only solution I see, use the oldest filesystem functions. Does anyone know another approach?Memoir
How to exlcude specific subfolders from zip? I have a name of that subfolders, how to exclude that?Cyathus
C
67

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

Canzone answered 6/2, 2011 at 17:25 Comment(10)
@netcoder - the benefits of having written the phpt for testing it... basically, read through the source for the ZipArchive class, and found it there.... there's also an undocumented addPattern() method that takes a regexp style pattern, but I've never managed to get that working (may be a bug in the class)Canzone
@kread - you can use this with any file list that can be extracted using glob(), so I've found it extremely useful since I discovered it.Canzone
@MarkBaker I know this comment is coming through years after you posted, I'm just trying my luck here. I've posted a question here about zipping as well. I'm about to try the glob method you posted here, but my main issue is that I can't use addFromString, and have been using addFile, which is just failing silently. Do you perhaps have any idea what might be going wrong, or what I might be doing wrong?Jemappes
@user1032531 - the last line of my post (edited 13th December 2013) indicates just that, with a link to the docs pageCanzone
Hmm, zipping seemed to work very well, though when I download the zip archive I had to try several decompression utilities before one would work--and the resulting unzipped folder was invisible. This is on OS X 10.9.5. Anybody else find this issue?Frau
Is addGlob recursive?Leningrad
@Vincent Poirier YesProsector
@RobertDundon I can't have addGlob recursive... Can you provide an example ?Quick
ZipArchive::open() returns a non-zero integer on failure, so checking if (!$zipArchive->open($zipFile, ZIPARCHIVE::OVERWRITE)) is invalid and just killed an hour of my time trying to debug! Have edited the answer accordingly.Martel
Also, using just ZipArchive::OVERWRITE will fail if the named file is not present, so use (ZipArchive::CREATE | ZipArchive::OVERWRITE) instead (assuming you want to create or overwrite as applicable).Martel
F
28

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.

Fritts answered 6/2, 2011 at 17:6 Comment(0)
P
22

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.

Priscillaprise answered 6/2, 2011 at 17:5 Comment(7)
It sure does delete some files in My folder, but i have also a folder within a folder My folder which gives me an error of: Permission denied by unlinking the folder with in My folderStillas
@Stupefy: Try if (!is_dir($file) && $file != 'target_folder...') instead. Or check @kread answer if you want to zip recursively, it's the most efficient way.Priscillaprise
The folder within the My folder is still not deleted, but there are no more errors anyway.Stillas
I also forgot to mention that i there are no .zip files created.Stillas
@Stepefy101: You never specified that you had or wanted subfolders to be deleted/zipped. If your path has a slash in it (e.g.: My Folder), you need to escape the space: My\ Folder when using glob, etc. I clearly stated that this method does not work recursively.Priscillaprise
Deleting the files before calling $zip->close() will not work. Check my answer hereEssex
Please replace this $zip->addFile($file); with :: $new_filename=end(explode("/",$file)); $zip->addFile($file,"emp/".$new_filename); This will customize your zip folder according to your own way.Funereal
C
19

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';
}
?>
Cutcherry answered 4/12, 2014 at 19:47 Comment(4)
Excellent solution. It works in laravel 5.5 too. really liked that. (y)Firebird
Great code! Clean, simple and perfectly working! ;) It seems for me the best reply. If it can help someone: I just added ini_set('memory_limit', '512M'); before the execution of the script and ini_restore('memory_limit'); at the end. It was necessary to avoid lack of memory in case of heavy folders (it was a folder bigger than 500MB).Cyrillus
In my environment (PHP 7.3, Debian) a ZIP archive without a directory listing was created (big, empty file). I had to change the following line: $name .= '/'; into $name = ($name == '.' ? '' : $name .'/');Quotidian
This is working for me. Thanks for sharing. Cheers!Albatross
M
10

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";
}
Microchemistry answered 27/10, 2013 at 9:1 Comment(1)
How to include sub-folders too in the backup automatically with this script? @AlirezaSharpedged
P
7

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');
Provenance answered 31/1, 2017 at 14:12 Comment(0)
P
4

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.

Pendulum answered 31/3, 2013 at 3:24 Comment(0)
F
3

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.

Frosty answered 18/8, 2021 at 16:13 Comment(0)
T
2

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();
Tarn answered 10/5, 2013 at 11:2 Comment(0)
B
2

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);
Banish answered 15/12, 2019 at 12:30 Comment(0)
F
1

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();
Funereal answered 25/11, 2014 at 7:3 Comment(0)
P
1

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.

Pianissimo answered 6/3, 2015 at 8:53 Comment(2)
I also have excluded the delete script , you can see the accepted answer for thisPianissimo
Gotta love those random down votes without a comment explaining why.Pianissimo
L
1

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;
}
Labiche answered 23/2, 2018 at 13:53 Comment(0)
B
0

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();
    ?>
Bassoon answered 27/7, 2014 at 14:27 Comment(1)
This do zip the files but the directory listing is gone it dose not have directory anymoreGillmore
J
0

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

Jemappes answered 18/3, 2015 at 9:38 Comment(0)
K
0

includes all sub-folders:

zip_folder('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):

function zip_folder ($input_folder, $output_zip_file) {
    $zipClass = new ZipArchive();
    if($input_folder !== false && $output_zip_file !== false)
    {
        $res = $zipClass->open($output_zip_file, \ZipArchive::CREATE);
        if($res === TRUE)   {
            // Add a Dir with Files and Subdirs to the archive
            $foldername = basename($input_folder);
            $zipClass->addEmptyDir($foldername);
            $foldername .= '/';         $input_folder .= '/';
            // Read all Files in Dir
            $dir = opendir ($input_folder);
            while ($file = readdir($dir))    {
                if ($file == '.' || $file == '..') continue;
                // Rekursiv, If dir: GoodZipArchive::addDir(), else ::File();
                $do = (filetype( $input_folder . $file) == 'dir') ? 'addDir' : 'addFile';
                $zipClass->$do($input_folder . $file, $foldername . $file);
            }
            $zipClass->close(); 
        }
        else   { exit ('Could not create a zip archive, migth be write permissions or other reason. Contact admin.'); }
    }
}
Karinakarine answered 14/4, 2021 at 18:7 Comment(0)
E
0

If you are sure you are doing everything correctly and it is still not working. Check your PHP (user) permissions.

Exhaust answered 21/6, 2022 at 19:14 Comment(2)
This looks like a commentWitted
This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From ReviewManumit
H
0

My 2 cents :

class compressor {
    
        /**
         * public static $NOT_COMPRESS
         * use: compressor::$NOT_COMPRESS
         * no compress thoses files for upload
         */
        public static $NOT_COMPRESS = array(
    
                'error_log',
                'cgi-bin',
                'whatever/whatever'
        );
        /**
         * end public static $NOT_COMPRESS
         */
    
    
        /**
         * public function compress_folder( $dir, $version, $archive_dest );
         * @param  {string}  $dir | absolute path to the directory
         * @param  {string}  $version_number | ex: 0.1.1
         * @param  {string}  $archive_dest | absolute path to the future compressed file
         * @return {void}    DO A COMPRESSION OF A FOLDER
         */
        public function compress_folder(  $dir, $version, $archive_dest  ){

    
                // name of FUTURE .zip file
                $archive_name = $version_number.'.zip';
    
                // test dir exits
                if( !is_dir($dir) ){ exit('No temp directory ...'); }
    
                // Iterate and archive API DIRECTORIES AND FOLDERS
    
                // create zip archive + manager
                $zip = new ZipArchive;
                $zip->open( $archive_dest,
                        ZipArchive::CREATE | ZipArchive::OVERWRITE );
    
                // iterator / SKIP_DOTS -> ignore '..' and '.'
                $it = new RecursiveIteratorIterator(
                       new RecursiveDirectoryIterator( $dir,
                       RecursiveDirectoryIterator::SKIP_DOTS )
                      );
    
                
                // loop iterator
                foreach( $it as $file ){
    
    
                        // check files not to add for compress 
    
                                // loop list for not add to upload .zip
                                foreach( compressor::$NOT_COMPRESS as $k => $v) {
    
                                        if( preg_match( '/^('.preg_quote($v,'/').')/', $it->getSubPathName() ) == true ){
    
    
                                                // break this loop and parent loop
                                                continue 2;
                                        }
                                }
                                // end loop list
    
                        // for Test
                        // echo $it->getSubPathName()."\r\n";
    
                        // no need to check if is a DIRECTORY with $it->getSubPathName()
                        // DIRECTORIES are added automatically
                        $zip->addFile( $it->getPathname(),  $it->getSubPathName() );
    
                }
                // end  loop
    
                $zip->close();
                // END Iterate and archive API DIRECTORIES AND FOLDERS
    
        }
        /**
         * public function compress_folder( $version_number );
         */

}
// end class compressor 

use :

// future name of the archive
$version = '0.0.1';

// path of directory to compress
$dir = $_SERVER['DOCUMENT_ROOT'].'/SOURCES';

// real path to FUTURE ARCHIVE
$archive_dest = $_SERVER['DOCUMENT_ROOT'].'/COMPRESSED/'.$version.'.zip';


$Compress = new compressor();
$Compress->compress_folder( $dir, $version, $archive_dest );

// this create a .zip file like : 
$_SERVER['DOCUMENT_ROOT'].'/COMPRESSED/0.0.1.zip
Harewood answered 21/10, 2022 at 4:44 Comment(2)
half of the class you supplied uses variables that are not defined... it is helpful, but not exactly working without loads of fiddling and changingDelectable
Thank you for your remark, I modified it to make it a more utilitarian functionHarewood
B
0

This is the best solution for me which is working fine in my Codecanyon project and well tested.

function zipper($space_slug)
{
// Get real path for our folder
$rootPath = realpath('files/' . $space_slug);

// Initialize archive object
$zip = new ZipArchive();
/* Opening the zip file and creating it if it doesn't exist. */
$zip->open('files/' . $space_slug . '.zip', ZipArchive::CREATE | 
ZipArchive::OVERWRITE);

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

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();
}
Blackshear answered 31/12, 2022 at 16:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.