with open clase archivos php directory zip directory-structure recursion

open - ¿Cómo[recursivamente] Zip un directorio en PHP?



un zip php (11)

Aquí está la función recursiva simple, fácil de leer que funciona muy 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();

El directorio es algo así como:

home/ file1.html file2.html Another_Dir/ file8.html Sub_Dir/ file19.html

Estoy usando la misma clase de PHP Zip utilizada en PHPMyAdmin http://trac.seagullproject.org/browser/branches/0.6-bugfix/lib/other/Zip.php . No estoy seguro de cómo comprimir un directorio en lugar de solo un archivo. Esto es lo que tengo hasta ahora:

$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

pero cuando intento descomprimir el archivo zip descargado correspondiente obtengo "operación no permitida"

Este error solo ocurre cuando intento descomprimir en mi mac, cuando descomprimo a través de la línea de comando el archivo se descomprime bien. ¿Debo enviar un tipo de contenido específico en la descarga, actualmente ''aplicación / zip''?


Aquí está mi código para comprimir las carpetas y sus subcarpetas y sus archivos y hacer que se pueda descargar en formato 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 surge un problema con el código, hágamelo saber.


Aquí está mi versión base en Alix, funciona en Windows y con suerte en * nix también:

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


Aquí hay una función simple que puede comprimir cualquier archivo o directorio recursivamente, solo necesita la extensión zip para ser cargada.

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

Llámalo así:

Zip(''/folder/to/compress/'', ''./compressed.zip'');


Este código funciona tanto para Windows como para 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(); }


Gran solución, pero para mi Windows necesito hacer modificaciones. Debajo del código de modificación

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


He editado la respuesta de para tomar un tercer texto, cuando establezco este tercer argumento como true todos los archivos se agregarán en el directorio principal en lugar de directamente en la carpeta zip.

Si el archivo zip existe, el archivo también se eliminará.

Ejemplo:

Zip(''/path/to/maindirectory'',''/path/to/compressed.zip'',true);

Tercer argrumento con true estructura zip:

maindirectory --- file 1 --- file 2 --- subdirectory 1 ------ file 3 ------ file 4 --- subdirectory 2 ------ file 5 ------ file 6

Tercer argrumento estructura postal false o faltante:

file 1 file 2 subdirectory 1 --- file 3 --- file 4 subdirectory 2 --- file 5 --- file 6

Código editado:

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


Necesitaba ejecutar esta función Zip en Mac OSX

así que siempre comprimiría esa molesta .DS_Store.

He adaptado incluyendo archivos adicionales de Ignore.

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 para ignorar .DS_Store de zip, ejecutas

zipIt (''/ path / to / folder'', ''/path/to/compressed.zip'', false, array (''. DS_Store''));


Otro archivo de árbol de directorios recursivo más, implementado como una extensión de ZipArchive. Como beneficio adicional, se incluye una función auxiliar de compresión de árbol de declaración única. El nombre local opcional es compatible, como en otras funciones de ZipArchive. Error al manejar el código que se agregará ...

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


Pruebe este enlace <- MÁS CÓDIGO FUENTE AQUÍ

/** 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''); ?>;


USO: thisfile.php? Dir =. / Ruta / a / carpeta (Después de comprimir, comienza la descarga también :)

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