如何在PHP中压缩目录?

目录是这样的:

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

我使用PHPMyAdmin中使用的相同的PHP Zip类http://trac.seagullproject.org/browser/branches/0.6-bugfix/lib/other/Zip.php 。 我不知道如何压缩一个目录而不是一个文件。 以下是我到目前为止:

 $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 

但是当我试图解压缩相应的下载zip文件时,我得到“操作不允许”

这个错误只发生在我试图在我的Mac上解压时,当我通过命令行解压缩文件解压缩好。 我需要发送一个特定的内容类型下载,目前“应用程序/邮编”

这是一个简单的函数,可以递归压缩任何文件或目录,只需要加载zip扩展。

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

像这样调用它:

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

另一个递归目录树归档,作为ZipArchive的扩展来实现。 作为奖励,还包括单语句树压缩助手函数。 支持可选的本地名称,就像在其他ZipArchive函数中一样。 处理要添加的代码的错误…

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

我已经编辑了Alix Axel的第三个问题的答案,将第三个参数设置为true所有文件都将被添加到主目录下,而不是直接在zip文件夹中。

如果压缩文件存在,文件也将被删除。

例:

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

第三个argrument true zip结构:

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

第三个false或缺少zip结构:

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

编辑的代码:

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

用法: thisfile.php?dir =。/ path / to / folder (压缩后,开始下载 🙂

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

试试这个链接 < – 更多的源代码在这里

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

这里是我的代码对于Zip文件夹及其子文件夹及其文件,并使其可以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); } 

如果任何问题与代码让我知道。

我需要在Mac OSX中运行这个Zip函数

所以我会永远压缩这令人讨厌的.DS_Store。

我通过包含additionalIgnore文件改编了https://stackoverflow.com/users/2019515/user2019515

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

所以要忽略从zip的.DS_Store,你运行

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

伟大的解决方案,但对于我的Windows我需要做一个修改。 下面的修改代码

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

这个页面中的代码效果更好

此代码适用于Windows和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(); } 

这里是我的基于Alix的版本,在Windows上工作,也希望在* 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(); }