web-dev-qa-db-fra.com

Comment compresser un dossier entier en utilisant PHP

J'ai trouvé ici à stackoveflow des codes sur la façon de compresser un fichier spécifique, mais que dire d'un dossier spécifique?

Folder/
  index.html
  picture.jpg
  important.txt

à l'intérieur de My Folder, il y a des fichiers. Après avoir compressé le My Folder, je souhaite également supprimer tout le contenu du dossier, à l'exception de important.txt.

Trouvé ceci ici à stack

J'ai besoin de ton aide. Merci.

106
woninana

Code mis à jour le 2015/04/22.

Zip un dossier entier:

// 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 $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();

Zip un dossier entier + supprime tous les fichiers sauf "important.txt":

// 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 $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);

        // 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);
}
262
Dador

Il existe une méthode non documentée utile dans la classe ZipArchive: addGlob ();

$zipFile = "./testZip.Zip";
$zipArchive = new ZipArchive();

if (!$zipArchive->open($zipFile, ZIPARCHIVE::OVERWRITE))
    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();

Maintenant documenté sur: www.php.net/manual/fr/ziparchive.addglob.php

47
Mark Baker

Essaye ça:

$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();

Ceci ne sera pas Zip récursivement cependant.

19
netcoder

Je suppose que cela fonctionne sur un serveur où l'application Zip est dans le chemin de recherche. Cela devrait être vrai pour tous les serveurs Unix et la plupart des serveurs Windows.

exec('Zip -r archive.Zip "My folder"');
unlink('My\ folder/index.html');
unlink('My\ folder/picture.jpg');

L'archive résidera dans archive.Zip par la suite. N'oubliez pas que les espaces dans les noms de fichiers ou de dossiers sont une cause fréquente d'erreurs et doivent être évités dans la mesure du possible. 

16
Kevin Read

J'ai essayé avec le code ci-dessous et cela fonctionne. Le code est explicite, merci de me contacter si vous avez des 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';
}
?>
11

C'est une fonction qui permet de compresser tout un dossier et son contenu dans un fichier Zip. Vous pouvez l'utiliser simplement comme ceci:

addzip ("path/folder/" , "/path2/folder.Zip" );

une fonction : 

// 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";
}
7
Alireza Fallah

Voici un exemple pratique de création de ZIP en 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();
1
Sun Love

Utilisez cette fonction:

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();
}

Exemple d'utilisation:

Zip('/folder/to/compress/', './compressed.Zip');
1
Waqar Alamgir

Utilisez cela fonctionne bien.

$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;
}
1
Indrajeet Singh

Pourquoi ne pas essayer Script multi-volume EFS PhP-Zip ... J'ai compressé et transféré des centaines de concerts et des millions de fichiers ... SSH est nécessaire pour créer efficacement des archives.

Mais je crois que les fichiers résultants peuvent être utilisés avec exec directement à partir de php:

exec('Zip -r backup-2013-03-30_0 . -i@backup-2013-03-30_0.txt');

Je ne sais pas si ça marche. Je n'ai pas essayé ...

"le secret" est que le temps d'exécution pour l'archivage ne doit pas dépasser le temps alloué pour l'exécution du code PHP.

1
ByREV

Pour tous ceux qui liront ce post et chercheront une raison pour compresser les fichiers en utilisant addFile au lieu de addFromString, cela ne compresse pas les fichiers avec leur chemin absolu (ne compresse que les fichiers et rien d’autre), consultez ma question et votre réponse ici

0
Skytiger

J'ai fait quelques petites améliorations dans le 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();
    ?>
0
Poohspear

Cela résoudra votre problème. Essayez-le.

$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();
0
Lakhan

J'ai trouvé ce post dans Google comme deuxième résultat final, le premier utilisait exec :( 

Quoi qu'il en soit, bien que cela ne réponde pas exactement à mes besoins, j'ai décidé de poster une réponse pour les autres avec ma version rapide mais étendue de ceci.

CARACTÉRISTIQUES DU SCRIPT

  • Nom du fichier de sauvegarde jour par jour, PREFIX-AAAA-MM-JJ-POSTFIX.EXTENSION
  • Rapport de fichier/manquant
  • Liste des sauvegardes précédentes
  • Ne compresse pas/n'inclut pas les sauvegardes précédentes;)
  • Fonctionne sous Windows/Linux

Quoi qu'il en soit, sur le script .. Bien que cela puisse sembler beaucoup .. Rappelez-vous qu'il y a un excès ici .. Alors n'hésitez pas à supprimer les sections de rapport si nécessaire ... 

En outre, cela peut paraître désordonné et certaines choses peuvent être nettoyées facilement ... Alors, ne commentez pas, c’est juste un script rapide avec des commentaires de base ajoutés .. PAS POUR UNE UTILISATION EN DIRECT .. !

Dans cet exemple, il est exécuté à partir d'un répertoire situé dans le dossier racine www/public_html. Il suffit donc de parcourir un dossier pour accéder à la racine.

<?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];
    }
?>

QU'EST CE QUE ÇA FAIT??

Il suffit de compresser le contenu complet de la variable $ pathBase et de stocker le fichier Zip dans le même dossier. Il effectue une détection simple des sauvegardes précédentes et les ignore.

CRON BACKUP

Ce script que je viens de tester sur Linux et qui a bien fonctionné à partir d’une tâche cron avec l’utilisation d’une URL absolue pour pathBase.

0
Mayhem