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

havelly commented Sep 22, 2015

Copy link
Copy Markdown

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

havelly commented Sep 25, 2015

Copy link
Copy Markdown

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

ximalog commented May 20, 2016

Copy link
Copy Markdown

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

KenanMurad commented Jul 14, 2016

Copy link
Copy Markdown

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

vmohir commented Sep 5, 2016

Copy link
Copy Markdown

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

kjin9174 commented Nov 8, 2017

Copy link
Copy Markdown

//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

kjin9174 commented Nov 8, 2017

Copy link
Copy Markdown

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

@kjin9174

kjin9174 commented Nov 9, 2017

Copy link
Copy Markdown

Hello, Everyone .
Help me. Please

@kjin9174

kjin9174 commented Nov 9, 2017

Copy link
Copy Markdown

done. I am ok

@kjin9174

kjin9174 commented Nov 9, 2017

Copy link
Copy Markdown

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

zillingen commented Dec 6, 2017

Copy link
Copy Markdown

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

vssoft commented Dec 30, 2019

Copy link
Copy Markdown

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

redfoc commented Jan 18, 2021

Copy link
Copy Markdown

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

arildr commented Mar 27, 2021

Copy link
Copy Markdown

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

vinoddesignomate commented Jan 12, 2022

Copy link
Copy Markdown

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