Le répertoire est quelque chose comme:
home/
file1.html
file2.html
Another_Dir/
file8.html
Sub_Dir/
file19.html
J'utilise le même PHP La classe ZIP utilisée dans PHPMyAdmin http://trac.seagullproject.org/browser/branches/0.6-bugfix/lib/other/Zip.php . Je ne suis pas sûr de savoir comment compresser un répertoire plutôt qu'un simple fichier. Voici ce que j'ai jusqu'à présent:
$aFiles = $this->da->getDirTree($target);
/* $aFiles is something like, path => filetime
Array
(
[home] =>
[home/file1.html] => 1251280379
[home/file2.html] => 1251280377
etc...
)
*/
$Zip = & new Zip();
foreach( $aFiles as $fileLocation => $time ){
$file = $target . "/" . $fileLocation;
if ( is_file($file) ){
$buffer = file_get_contents($file);
$Zip->addFile($buffer, $fileLocation);
}
}
THEN_SOME_PHP_CLASS::toDownloadData($Zip); // this bit works ok
mais lorsque j'essaie de décompresser le fichier Zip téléchargé correspondant, le message "opération non autorisée" s'affiche.
Cette erreur ne se produit que lorsque j'essaie de décompresser sur mon Mac, lorsque je décompresse le fichier en ligne de commande, le fichier est bien décompressé. Dois-je envoyer un type de contenu spécifique lors du téléchargement, actuellement "application/Zip"?
Voici une fonction simple qui peut compresser n'importe quel fichier ou répertoire de manière récursive, il suffit que l'extension Zip soit chargée.
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 . '/'));
}
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();
}
Appelez ça comme ça:
Zip('/folder/to/compress/', './compressed.Zip');
Encore un autre archivage récursif d'arborescence de répertoires, implémenté comme une extension de ZipArchive. En prime, une fonction d'assistance à la compression d'arborescence à une seule instruction est incluse. Le nom local facultatif est pris en charge, comme dans d'autres fonctions ZipArchive. Erreur de gestion du code à ajouter ...
class ExtendedZip extends ZipArchive {
// Member function to add a whole file system subtree to the archive
public function addTree($dirname, $localname = '') {
if ($localname)
$this->addEmptyDir($localname);
$this->_addTree($dirname, $localname);
}
// Internal function, to recurse
protected function _addTree($dirname, $localname) {
$dir = opendir($dirname);
while ($filename = readdir($dir)) {
// Discard . and ..
if ($filename == '.' || $filename == '..')
continue;
// Proceed according to type
$path = $dirname . '/' . $filename;
$localpath = $localname ? ($localname . '/' . $filename) : $filename;
if (is_dir($path)) {
// Directory: add & recurse
$this->addEmptyDir($localpath);
$this->_addTree($path, $localpath);
}
else if (is_file($path)) {
// File: just add
$this->addFile($path, $localpath);
}
}
closedir($dir);
}
// Helper function
public static function zipTree($dirname, $zipFilename, $flags = 0, $localname = '') {
$Zip = new self();
$Zip->open($zipFilename, $flags);
$Zip->addTree($dirname, $localname);
$Zip->close();
}
}
// Example
ExtendedZip::zipTree('/foo/bar', '/tmp/archive.Zip', ZipArchive::CREATE);
J'ai modifié la réponse de Alix Axel à prendre un troisième argument. Lorsque vous définissez ce troisième argument sur true
, tous les fichiers seront ajoutés dans le répertoire principal plutôt que directement dans le zip. dossier.
Si le fichier Zip existe, le fichier sera également supprimé.
Exemple:
Zip('/path/to/maindirectory','/path/to/compressed.Zip',true);
Troisième argument true
Structure Zip:
maindirectory
--- file 1
--- file 2
--- subdirectory 1
------ file 3
------ file 4
--- subdirectory 2
------ file 5
------ file 6
Troisième argument false
ou structure Zip manquante:
file 1
file 2
subdirectory 1
--- file 3
--- file 4
subdirectory 2
--- file 5
--- file 6
Code édité:
function Zip($source, $destination, $include_dir = false)
{
if (!extension_loaded('Zip') || !file_exists($source)) {
return false;
}
if (file_exists($destination)) {
unlink ($destination);
}
$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);
if ($include_dir) {
$arr = explode("/",$source);
$maindir = $arr[count($arr)- 1];
$source = "";
for ($i=0; $i < count($arr) - 1; $i++) {
$source .= '/' . $arr[$i];
}
$source = substr($source, 1);
$Zip->addEmptyDir($maindir);
}
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 . '/'));
}
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();
}
UTILISATION: thisfile.php? Dir =./Chemin/vers/dossier (Après avoir compressé, il démarre télécharger aussi :)
<?php
$exclude_some_files=
array(
'mainfolder/folder1/filename.php',
'mainfolder/folder5/otherfile.php'
);
//***************built from https://Gist.github.com/ninadsp/6098467 ******
class ModifiedFlxZipArchive extends ZipArchive {
public function addDirDoo($location, $name , $prohib_filenames=false) {
if (!file_exists($location)) { die("maybe file/folder path incorrect");}
$this->addEmptyDir($name);
$name .= '/';
$location.= '/';
$dir = opendir ($location); // Read all Files in Dir
while ($file = readdir($dir)){
if ($file == '.' || $file == '..') continue;
if (!in_array($name.$file,$prohib_filenames)){
if (filetype( $location . $file) == 'dir'){
$this->addDirDoo($location . $file, $name . $file,$prohib_filenames );
}
else {
$this->addFile($location . $file, $name . $file);
}
}
}
}
public function downld($Zip_name){
ob_get_clean();
header("Pragma: public"); header("Expires: 0"); header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private", false); header("Content-Type: application/Zip");
header("Content-Disposition: attachment; filename=" . basename($Zip_name) . ";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . filesize($Zip_name));
readfile($Zip_name);
}
}
//set memory limits
set_time_limit(3000);
ini_set('max_execution_time', 3000);
ini_set('memory_limit','100M');
$new_Zip_filename='down_Zip_file_'.Rand(1,1000000).'.Zip';
// Download action
if (isset($_GET['dir'])) {
$za = new ModifiedFlxZipArchive;
//create an archive
if ($za->open($new_Zip_filename, ZipArchive::CREATE)) {
$za->addDirDoo($_GET['dir'], basename($_GET['dir']), $exclude_some_files); $za->close();
}else {die('cantttt');}
if (isset($_GET['dir'])) {
$za = new ModifiedFlxZipArchive;
//create an archive
if ($za->open($new_Zip_filename, ZipArchive::CREATE)) {
$za->addDirDoo($_GET['dir'], basename($_GET['dir']), $exclude_some_files); $za->close();
}else {die('cantttt');}
//download archive
//on the same execution,this made problems in some hostings, so better redirect
//$za -> downld($new_Zip_filename);
header("location:?fildown=".$new_Zip_filename); exit;
}
if (isset($_GET['fildown'])){
$za = new ModifiedFlxZipArchive;
$za -> downld($_GET['fildown']);
}
?>
Essayez ce lien <- PLUS DE CODE SOURCE ICI
/** Include the Pear Library for Zip */
include ('Archive/Zip.php');
/** Create a Zipping Object...
* Name of Zip file to be created..
* You can specify the path too */
$obj = new Archive_Zip('test.Zip');
/**
* create a file array of Files to be Added in Zip
*/
$files = array('black.gif',
'blue.gif',
);
/**
* creating Zip file..if success do something else do something...
* if Error in file creation ..it is either due to permission problem (Solution: give 777 to that folder)
* Or Corruption of File Problem..
*/
if ($obj->create($files)) {
// echo 'Created successfully!';
} else {
//echo 'Error in file creation';
}
?>; // We'll be outputting a Zip
header('Content-type: application/Zip');
// It will be called test.Zip
header('Content-Disposition: attachment; filename="test.Zip"');
//read a file and send
readfile('test.Zip');
?>;
Voici mon code pour Zip les dossiers et ses sous-dossiers et ses fichiers et le rendre téléchargeable au format Zip
function Zip()
{
$source='path/folder'// Path To the folder;
$destination='path/folder/abc.Zip'// Path to the file and file name ;
$include_dir = false;
$archive = 'abc.Zip'// File Name ;
if (!extension_loaded('Zip') || !file_exists($source)) {
return false;
}
if (file_exists($destination)) {
unlink ($destination);
}
$Zip = new ZipArchive;
if (!$Zip->open($archive, ZipArchive::CREATE)) {
return false;
}
$source = str_replace('\\', '/', realpath($source));
if (is_dir($source) === true)
{
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);
if ($include_dir) {
$arr = explode("/",$source);
$maindir = $arr[count($arr)- 1];
$source = "";
for ($i=0; $i < count($arr) - 1; $i++) {
$source .= '/' . $arr[$i];
}
$source = substr($source, 1);
$Zip->addEmptyDir($maindir);
}
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 . '/'));
}
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));
}
$Zip->close();
header('Content-Type: application/Zip');
header('Content-disposition: attachment; filename='.$archive);
header('Content-Length: '.filesize($archive));
readfile($archive);
unlink($archive);
}
Si un problème avec le code, faites le moi savoir.
Ce code fonctionne pour Windows et Linux.
function Zip($source, $destination)
{
if (!extension_loaded('Zip') || !file_exists($source)) {
return false;
}
$Zip = new ZipArchive();
if (!$Zip->open($destination, ZIPARCHIVE::CREATE)) {
return false;
}
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
DEFINE('DS', DIRECTORY_SEPARATOR); //for windows
} else {
DEFINE('DS', '/'); //for linux
}
$source = str_replace('\\', DS, realpath($source));
if (is_dir($source) === true)
{
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);
echo $source;
foreach ($files as $file)
{
$file = str_replace('\\',DS, $file);
// Ignore "." and ".." folders
if( in_array(substr($file, strrpos($file, DS)+1), array('.', '..')) )
continue;
$file = realpath($file);
if (is_dir($file) === true)
{
$Zip->addEmptyDir(str_replace($source . DS, '', $file . DS));
}
else if (is_file($file) === true)
{
$Zip->addFromString(str_replace($source . DS, '', $file), file_get_contents($file));
}
echo $source;
}
}
else if (is_file($source) === true)
{
$Zip->addFromString(basename($source), file_get_contents($source));
}
return $Zip->close();
}
Voici la fonction simple, facile à lire, récursive qui fonctionne très bien:
function Zip_r($from, $Zip, $base=false) {
if (!file_exists($from) OR !extension_loaded('Zip')) {return false;}
if (!$base) {$base = $from;}
$base = trim($base, '/');
$Zip->addEmptyDir($base);
$dir = opendir($from);
while (false !== ($file = readdir($dir))) {
if ($file == '.' OR $file == '..') {continue;}
if (is_dir($from . '/' . $file)) {
Zip_r($from . '/' . $file, $Zip, $base . '/' . $file);
} else {
$Zip->addFile($from . '/' . $file, $base . '/' . $file);
}
}
return $Zip;
}
$from = "/path/to/folder";
$base = "basezipfolder";
$Zip = new ZipArchive();
$Zip->open('zipfile.Zip', ZIPARCHIVE::CREATE);
$Zip = Zip_r($from, $Zip, $base);
$Zip->close();
Voici ma version de base sur celle d'Alix, fonctionne sous Windows et, espérons-le aussi, sur * nix:
function addFolderToZip($source, $destination, $flags = ZIPARCHIVE::OVERWRITE)
{
$source = realpath($source);
$destination = realpath($destination);
if (!file_exists($source)) {
die("file does not exist: " . $source);
}
$Zip = new ZipArchive();
if (!$Zip->open($destination, $flags )) {
die("Cannot open Zip archive: " . $destination);
}
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);
$sourceWithSeparator = $source . DIRECTORY_SEPARATOR;
foreach ($files as $file)
{
// Ignore "." and ".." folders
if(in_array(substr($file,strrpos($file, DIRECTORY_SEPARATOR)+1),array('.', '..')))
continue;
if (is_dir($file) === true)
{
$Zip->addEmptyDir(
str_replace($sourceWithSeparator, '', $file . DIRECTORY_SEPARATOR));
}
else if (is_file($file) === true)
{
$Zip->addFile($file, str_replace($sourceWithSeparator, '', $file));
}
}
return $Zip->close();
}
Excellente solution, mais pour Windows, il me faut apporter des modifications. En dessous du code de modification
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;
if (is_dir($file) === true)
{
$Zip->addEmptyDir(str_replace($source . '/', '', $file));
}
else if (is_file($file) === true)
{
$str1 = str_replace($source . '/', '', '/'.$file);
$Zip->addFromString($str1, file_get_contents($file));
}
}
}
else if (is_file($source) === true)
{
$Zip->addFromString(basename($source), file_get_contents($source));
}
return $Zip->close();
}
J'avais besoin d'exécuter cette fonction Zip sous Mac OSX
donc je voudrais toujours compresser ce .DS_Store.
Je me suis adapté https://stackoverflow.com/users/2019515/user2019515 en incluant des fichiers additionalIgnore.
function zipIt($source, $destination, $include_dir = false, $additionalIgnoreFiles = array())
{
// Ignore "." and ".." folders by default
$defaultIgnoreFiles = array('.', '..');
// include more files to ignore
$ignoreFiles = array_merge($defaultIgnoreFiles, $additionalIgnoreFiles);
if (!extension_loaded('Zip') || !file_exists($source)) {
return false;
}
if (file_exists($destination)) {
unlink ($destination);
}
$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);
if ($include_dir) {
$arr = explode("/",$source);
$maindir = $arr[count($arr)- 1];
$source = "";
for ($i=0; $i < count($arr) - 1; $i++) {
$source .= '/' . $arr[$i];
}
$source = substr($source, 1);
$Zip->addEmptyDir($maindir);
}
foreach ($files as $file)
{
$file = str_replace('\\', '/', $file);
// purposely ignore files that are irrelevant
if( in_array(substr($file, strrpos($file, '/')+1), $ignoreFiles) )
continue;
$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();
}
SO pour ignorer le .DS_Store de Zip, vous exécutez
zipIt ('/ path/to/folder', '/path/to/compressed.Zip', false, array ('.DS_Store'));