Script para comprimir directorios y archivos recursivamente permitiendo excluir algunos

  • 3 Feb 2016
  • PHP

Ideal para crear backups periódicos (con el agregado de un cron) dentro un hosting compartido del que se tienen pocas libertades de acción.

Parámetros

Al script deben pasarse 4 variables:

backup_files
Ubicación de la que se desea crear el paquete
backup_file_name
Nombre de archivo del paquete
exclude_dir
Lista de directorios para excluir del paquete
download_file
Boolean para indicar si se desea descargar el archivo .zip una vez creado (true) o si basta solo crearlo (false)

El código

Código del script con algunos valores de ejemplo

<?php

$backup_files = '.';
$backup_file_name = '/home/username/public_html/www/backups/backup.zip';

if (!touch($backup_file_name)) {
  print "Can't open/create file {$backup_file_name}. Permission denied.";
  exit();
}

$exclude_dir = array(
  "./cache",
  "./exclude",
);

$download_file= false;
 
class FlxZipArchive extends ZipArchive {
    /** Add a Dir with Files and Subdirs to the archive;;;;; 
        @param string $location Real Location;;;;  
        @param string $name Name in Archive;;; 
        @author Nicolas Heimann;;;; 
        @access private  
    **/
 
    public function addDir($location, $name) {
        $this->addEmptyDir($name);
 
        $this->addDirDo($location, $name);
     } // EO addDir;
 
    /**  Add Files & Dirs to archive;;;; 
        @param string $location Real Location;  
        @param string $name Name in Archive;;;;;; 
        @author Nicolas Heimann
        @access private   
    **/
    
    private function exclude($location) {
        global $exclude_dir;
        for($n = 0; $n < count($exclude_dir); $n++){
          if (strpos($location, $exclude_dir[$n]) === 0) {
            return TRUE;
          }
        }
        return FALSE;
    }
    
    private function addDirDo($location, $name) {
        global $exclude_dir;
        $name .= '/';
        $location .= '/';
 
        // Read all Files in Dir
        $dir = opendir ($location);
        while ($file = readdir($dir))
        {
            if ($file == '.' || $file == '..') {
              continue;
            }
            
            if ($this->exclude($location.$file)) {
              continue;
            }
            
            // Rekursiv, If dir: FlxZipArchive::addDir(), else ::File();
            $do = (filetype( $location . $file) == 'dir') ? 'addDir' : 'addFile';
            $this->$do($location . $file, $name . $file);
        }
    } // EO addDirDo();
}
 
$za = new FlxZipArchive;
$res = $za->open($backup_file_name, ZipArchive::CREATE);
if($res === TRUE) 
{
    $za->addDir($backup_files, basename($backup_files));
    $za->close();
}
else  { echo 'Could not create a zip archive';}
 
if ($download_file)
{
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename="'.basename($backup_file_name).'"');
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize($backup_file_name));
    readfile($backup_file_name);
    exit; 
}