Skip to content

Instantly share code, notes, and snippets.

@menzerath
Last active February 18, 2024 19:33
Show Gist options
  • Select an option

  • Save menzerath/4185113 to your computer and use it in GitHub Desktop.

Select an option

Save menzerath/4185113 to your computer and use it in GitHub Desktop.
PHP: Recursively Backup Files & Folders to ZIP-File
<?php
/*
* PHP: Recursively Backup Files & Folders to ZIP-File
* MIT-License - 2012-2018 Marvin Menzerath
*/
// 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($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)) {
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS), 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;
}
?>
@havelly
Copy link
Copy Markdown

havelly 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
Copy link
Copy Markdown

havelly 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
Copy link
Copy Markdown

ximalog 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
Copy link
Copy Markdown

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.

@hm-software56
Copy link
Copy Markdown

Good

@KenanMurad
Copy link
Copy Markdown

KenanMurad commented Jul 14, 2016

It did not work for me

@tallesairan
Copy link
Copy Markdown

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

@vmohir
Copy link
Copy Markdown

vmohir 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
Copy link
Copy Markdown

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

@desmogiuse
Copy link
Copy Markdown

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
Copy link
Copy Markdown

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

@kjin9174
Copy link
Copy Markdown

kjin9174 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
Copy link
Copy Markdown

kjin9174 commented Nov 8, 2017

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

@kjin9174
Copy link
Copy Markdown

kjin9174 commented Nov 9, 2017

Hello, Everyone .
Help me. Please

@kjin9174
Copy link
Copy Markdown

kjin9174 commented Nov 9, 2017

done. I am ok

@kjin9174
Copy link
Copy Markdown

kjin9174 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
Copy link
Copy Markdown

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
Copy link
Copy Markdown

zillingen 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
Copy link
Copy Markdown

it's working fine thank u

@nasiruddin786
Copy link
Copy Markdown

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

@mayanknetqom
Copy link
Copy Markdown

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
Copy link
Copy Markdown

@toddsby Thanks!

@vssoft
Copy link
Copy Markdown

vssoft commented Dec 30, 2019

I use this both on Linux and Windows:

$source = <absolute pathname to directory/file to be zipped> . DIRECTORY_SEPARATOR;
$fileName = "myfiles.zip";
$destination = <absolute pathname to destination directory> . DIRECTORY_SEPARATOR . $fileName;

function zip_files( $source, $destination ) 
{
  $zip = new ZipArchive();
  if($zip->open($destination, ZIPARCHIVE::CREATE) === true) {
    $source = realpath($source);
    if(is_dir($source)) {
      $iterator = new RecursiveDirectoryIterator($source);
      $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 . DIRECTORY_SEPARATOR, '', $file . DIRECTORY_SEPARATOR));
        }elseif(is_file($file)) {
          $zip->addFile($file,str_replace($source . DIRECTORY_SEPARATOR, '', $file));
        }
      }
    }elseif(is_file($source)) {
      $zip->addFile($source,basename($source));
    }
  }
  return $zip->close();
}

@prashantkumarabhishek
Copy link
Copy Markdown

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

Just replace few line and this issue will solve, everytime it will create a new zip
$dest=time()."backup.zip";
zipData('screenshots', $dest);
echo 'Finished.';

@pareshsojitra
Copy link
Copy Markdown

Hi,
@prashantkumarabhishek
You are right, But make sure to do not keep backups in site root. Keep it in Hosting root.
Thank you.

@Thomasfds
Copy link
Copy Markdown

Maybe include "exclude folder/file" option now ?

@redfoc
Copy link
Copy Markdown

redfoc commented Jan 18, 2021

Add ignored list (Array) and directory separator compatibility

`function zipData($source, $destination, $ignores = []) {
if (extension_loaded('zip')) {
if (file_exists($source)) {
$zip = new ZipArchive();
if ($zip->open($destination, ZIPARCHIVE::CREATE)) {
if (is_dir($source)) {
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST);
foreach ($files as $file) {

					$ignored = false;

					foreach ($ignores as $ignore) {
						if(strpos($file, $ignore)){
							$ignored = true;
							break;
						}
					}

					if($ignored){
						continue;
					}

					if (is_dir($file)) {
						$zip->addEmptyDir(str_replace($source . DIRECTORY_SEPARATOR, '', $file . DIRECTORY_SEPARATOR));
					} else if (is_file($file)) {
						echo(str_replace($source . DIRECTORY_SEPARATOR, '', $file . DIRECTORY_SEPARATOR).'<br>');
						$zip->addFromString(str_replace($source . DIRECTORY_SEPARATOR, '', $file), file_get_contents($file));
					}
				}
			} else if (is_file($source)) {
				$zip->addFromString(basename($source), file_get_contents($source));
			}
		}
		return $zip->close();
	}
}
return false;

}`

@arildr
Copy link
Copy Markdown

arildr commented Mar 27, 2021

In the same lane.
What about a backup program which takes files from a dir and all subdirs newer than a specific date and zips it.

@parkcheck
Copy link
Copy Markdown

I cant get it to work. is this not working with newer PHP versions? 7.2?

@vinoddesignomate
Copy link
Copy Markdown

vinoddesignomate commented Jan 12, 2022

is this code can create zip up 10 GB files into backup of any sites ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment