Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
PHP: Recursively Backup Files & Folders to ZIP-File
<?php
/*
* PHP Recursive Backup-Script to ZIP-File
* (c) 2012: Marvin Menzerath. (http://menzerath.eu)
*/
// Make sure the script can handle large folders/files
ini_set('max_execution_time', 600);
ini_set('memory_limit','1024M');
// Start the backup!
zipData('/path/to/folder', '/path/to/backup.zip');
echo 'Finished.';
// Here the magic happens :)
function zipData($folder, $zipTo) {
if (extension_loaded('zip') === true) {
if (file_exists($source) === true) {
$zip = new ZipArchive();
if ($zip->open($destination, ZIPARCHIVE::CREATE) === true) {
$source = realpath($source);
if (is_dir($source) === true) {
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);
foreach ($files as $file) {
$file = realpath($file);
if (is_dir($file) === true) {
$zip->addEmptyDir(str_replace($source . '/', '', $file . '/'));
} else if (is_file($file) === true) {
$zip->addFromString(str_replace($source . '/', '', $file), file_get_contents($file));
}
}
} else if (is_file($source) === true) {
$zip->addFromString(basename($source), file_get_contents($source));
}
}
return $zip->close();
}
}
return false;
}
?>
@carltondickson

This comment has been minimized.

Copy link

commented Jul 31, 2014

Works perfectly, zipping a directory recursively should be something the extensions provides IMO.
Thanks for sharing.

@cristianp6

This comment has been minimized.

Copy link

commented Sep 3, 2014

Thanks for this, works fine, but you've to change the function arguments from:
function zipData($folder, $zipTo)
to:
function zipData($source, $destination)

@toddsby

This comment has been minimized.

Copy link

commented Dec 5, 2014

great work, slightly tweaked to prevent unwanted recursion. (see line 24, 25)
https://gist.github.com/toddsby/f98d82314259ec5483d8

    function zipData($source, $destination) {
        if (extension_loaded('zip')) {
            if (file_exists($source)) {
                $zip = new ZipArchive();
                if ($zip->open($destination, ZIPARCHIVE::CREATE)) {
                    $source = realpath($source);
                    if (is_dir($source)) {
                        $iterator = new RecursiveDirectoryIterator($source);
                        // skip dot files while iterating 
                        $iterator->setFlags(RecursiveDirectoryIterator::SKIP_DOTS);
                        $files = new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::SELF_FIRST);
                        foreach ($files as $file) {
                            $file = realpath($file);
                            if (is_dir($file)) {
                                $zip->addEmptyDir(str_replace($source . '/', '', $file . '/'));
                            } else if (is_file($file)) {
                                $zip->addFromString(str_replace($source . '/', '', $file), file_get_contents($file));
                            }
                        }
                    } else if (is_file($source)) {
                        $zip->addFromString(basename($source), file_get_contents($source));
                    }
                }
                return $zip->close();
            }
        }
        return false;
    }
@Burnett01

This comment has been minimized.

Copy link

commented Apr 8, 2015

Works like charm, thanks. Also don't forget to chmod your folder, people ;)

@ajdumanhug

This comment has been minimized.

Copy link

commented May 31, 2015

Hello,

Can someone help me how to make this backup work?
I'm a Newbie PHP Developer and I am using CodeIgniter as PHP FrameWork.

@kp52

This comment has been minimized.

Copy link

commented Jun 18, 2015

Thanks for this. It has helped build a new backup utility I'm working on

@havelly

This comment has been minimized.

Copy link

commented Sep 22, 2015

It does not appear to be working for me.

Have made the change mentioned above:
function zipData($folder, $zipTo)
to:
function zipData($source, $destination)

Not sure what chmod is.

Any suggestions?

@havelly

This comment has been minimized.

Copy link

commented Sep 25, 2015

As previously noted this program did not work for me. The above people who had success may have been using unix - it would be interesting to know if that was the case.

For Windows users (i'm presuming this is the point of difference) there is a minor change needed. Where ever the forward slash is used it needs to be replaced with a backslash and of course escaped.

So there are two lines of code that need to be modified as shown below:

$zip->addEmptyDir(str_replace($source . '\', '', $file . '\'));
$zip->addFromString(str_replace($source . '\', '', $file), file_get_contents($file));

@ximalog

This comment has been minimized.

Copy link

commented May 20, 2016

it worked for me ,i only assigned value to source variable i.e $source="upload"; then did the escaping for windows. thanks sirgentcode from nigeria

@theking2

This comment has been minimized.

Copy link

commented May 30, 2016

It works, but one problem is that it resets the date/time to the moment the backup was made, not when the original file/folder was made. I rely on these rather crude numbers to find out modifications.

@ntajxyooj

This comment has been minimized.

Copy link

commented Jul 5, 2016

Good

@KenanMurad

This comment has been minimized.

Copy link

commented Jul 14, 2016

It did not work for me

@tallesairan

This comment has been minimized.

Copy link

commented Jul 31, 2016

For windows use this code

function zipData($source, $destination) {
if (extension_loaded('zip')) {
if (file_exists($source)) {
$zip = new ZipArchive();
if ($zip->open($destination, ZIPARCHIVE::CREATE)) {
$source = realpath($source);
if (is_dir($source)) {
$iterator = new RecursiveDirectoryIterator($source);
// skip dot files while iterating
$iterator->setFlags(RecursiveDirectoryIterator::SKIP_DOTS);
$files = new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::SELF_FIRST);
foreach ($files as $file) {
$file = realpath($file);
if (is_dir($file)) {
$zip->addEmptyDir(str_replace($source . '', '', $file . ''));
} else if (is_file($file)) {
$zip->addFromString(str_replace($source . '', '', $file), file_get_contents($file));
}
}
} else if (is_file($source)) {
$zip->addFromString(basename($source), file_get_contents($source));
}
}
return $zip->close();
}
}
return false;
}
worked for me

@gvmohzibat

This comment has been minimized.

Copy link

commented Sep 5, 2016

Thanks It works. A note for beginners:
You should change this code:
zipData('myfolder', 'backup.zip');
The first line is a folder the is beside backup.php. So "myfolder" and backup.php are in one folder.

@professorhaseeb

This comment has been minimized.

Copy link

commented Oct 12, 2016

when the files are extracted, their permissions is not the same. i'm using php version 5.6.23

@desmogiuse

This comment has been minimized.

Copy link

commented Sep 1, 2017

I added a check for empty dir, so that downloading the zip file doesn't throw an error

`<?php function zipData($source, $destination) {

//Added check for empty dir, so that downloading the zip file doesn't throw an error
if (extension_loaded('zip') && file_exists($source) && count(glob($source . DS . '*')) !== 0) {

        $zip = new \ZipArchive();
        if ($zip->open($destination, \ZIPARCHIVE::CREATE)) {
            $source = realpath($source);
            if (is_dir($source)) {
                $iterator = new \RecursiveDirectoryIterator($source);
                // skip dot files while iterating
                $iterator->setFlags(RecursiveDirectoryIterator::SKIP_DOTS);
                $files = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);

                foreach ($files as $file) {
                    $file = realpath($file);
                    if (is_dir($file)) {
                        $zip->addEmptyDir(str_replace($source . '', '', $file . ''));
                    } else if (is_file($file)) {
                        $zip->addFromString(str_replace($source . '', '', $file), file_get_contents($file));
                    }
                }
            } else if (is_file($source)) {
                $zip->addFromString(basename($source), file_get_contents($source));
            }
        }
        return $zip->close();
    }

return false;

}
?>`

@renetheberge

This comment has been minimized.

Copy link

commented Oct 26, 2017

My backup folder is within the root directory. How do I exclude the backup folder?

@kjin9174

This comment has been minimized.

Copy link

commented Nov 8, 2017

//kjin uploads file backup
function zipData($source, $destination) {
if (extension_loaded('zip')) {
if (file_exists($source)) {
$zip = new ZipArchive();
if ($zip->open($destination, ZIPARCHIVE::CREATE)) {
$source = realpath($source);
echo $source;
if (is_dir($source)) {
$iterator = new RecursiveDirectoryIterator($source);
// skip dot files while iterating
$iterator->setFlags(RecursiveDirectoryIterator::SKIP_DOTS);
$files = new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::SELF_FIRST);
foreach ($files as $file) {
$file = realpath($file);
if (is_dir($file)) {
$zip->addEmptyDir(str_replace($source . '/', '', $file . '/'));
} else if (is_file($file)) {
$zip->addFromString(str_replace($source . '/', '', $file), file_get_contents($file));
}
}
} else if (is_file($source)) {
$zip->addFromString(basename($source), file_get_contents($source));
}
}
return $zip->close();
}
}
return false;
}

    ini_set('max_execution_time', 600);
    ini_set('memory_limit','1024M');
    zipData($upload_dir['basedir'], content_url().'/backup.zip');

It is not working

@kjin9174

This comment has been minimized.

Copy link

commented Nov 8, 2017

Help me
Code has done in wp
but i couldn't see zip file

@kjin9174

This comment has been minimized.

Copy link

commented Nov 9, 2017

Hello, Everyone .
Help me. Please

@kjin9174

This comment has been minimized.

Copy link

commented Nov 9, 2017

done. I am ok

@kjin9174

This comment has been minimized.

Copy link

commented Nov 9, 2017

And then i gonna restore from backup
But i couldn't get filename and ext, path of backup zip files after uploading in php
Everyone help me.
if you are interested here
Thanks. will wait

@kjin9174

This comment has been minimized.

Copy link

commented Nov 17, 2017

Hello, everyone.
How are you?
I am facing allowed memory error about zip file creation of 10gbyte directory with 3gbyte zip file.
so i googled.
There says that i should removing file_get_contents and use addFile function.
But it is now working.
I hope you help me and i get backup any file size by this github
Thanks.

@zillingen

This comment has been minimized.

Copy link

commented Dec 6, 2017

Nice script. But i use addFile instead addFromString in my backup script:

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

    foreach ($files as $file) {
        $file = realpath($file);

        if (is_dir($file) === true) {
            $zip->addEmptyDir(str_replace($source . '/', '', $file . '/'));

        } else if (is_file($file) === true) {
            $zip->addFile($file, str_replace($source . '/', '', $file));
        }
    }
} else if (is_file($source) === true) {
        $zip->addFile($source, basename($source));
}
// ...code
@prasanthi-nallamothu

This comment has been minimized.

Copy link

commented Jan 25, 2018

it's working fine thank u

@nasiruddin786

This comment has been minimized.

Copy link

commented Jul 2, 2018

how can i change dir and file name for each loop through data ??????

@mayanknetqom

This comment has been minimized.

Copy link

commented Nov 12, 2018

Hello Everyone,
Thanks for providing such a nice script to create an archive using php.
I have used this code to create backups of my website.
The code is working perfectly fine but I have an issue i.e. when I run this script at very first, it creates an archive - that is good but if I run the script again it creates an archive which overrides the previous one and includes that old archive into new one.
I want to exclude .zip files from compression.
Can you please help me in this matter?
I want to create an archive which should not contain any archive or .zip file into it.
I will be waiting for kind and positive response.
Thanks & Regards,
Mayank

@bodnar1212

This comment has been minimized.

Copy link

commented Apr 4, 2019

@toddsby Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.