如何使用 PHP 压缩整个文件夹

我在 stackovflow 上找到了一些关于如何压缩特定文件的代码,但是如何压缩特定文件夹呢?

Folder/
index.html
picture.jpg
important.txt

My Folder里面,有文件。在压缩 My Folder之后,我还想删除除 important.txt之外的文件夹的所有内容。

发现了这个

我需要你的帮助。 谢谢。

286450 次浏览

试试这个:

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

但是这个 不会是递归压缩的。

我假设这是在 zip 应用程序位于搜索路径中的服务器上运行的。对于所有基于 unix 的服务器应该都是如此,我猜大多数基于 Windows 的服务器也是如此。

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

之后,归档文件将驻留在 archive. zip 中。请记住,文件或文件夹名称中的空白是导致错误的常见原因,应尽可能避免。

更新2015/04/22年度守则。

把整个文件夹压缩:

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

压缩整个文件夹 + 删除所有文件,除了“ impant.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);
}

ZipArchive 类中有一个有用的非文档化方法: addGlob () ;

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


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

现在记录在: Www.php.net/manual/en/ziparchive.addglob.php

为什么不尝试 多卷脚本... 我压缩并传输了数百个 G 和数百万个文件... ssh 是有效创建归档所必需的。

但是我相信结果文件可以直接从 php 中与 exec 一起使用:

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

我不知道它是否工作。我没有尝试..。

“秘诀”是归档的执行时间不应该超过 PHP 代码的允许执行时间。

这是在 PHP 中制作 ZIP 的一个工作示例:

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

这是一个函数,它将整个文件夹及其内容压缩到一个压缩文件中,您可以像这样简单地使用它:

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

功能:

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

我对剧本做了一些小小的改进。

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

这能解决你的问题,请试试。

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

我尝试用下面的代码,它是工作。该代码是不言而喻的,如果您有任何问题,请让我知道。

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

我发现这篇文章在谷歌作为第二顶结果,第一是使用 exec: (

无论如何,虽然这并不完全符合我的需要。.我决定用我的快速但是扩展的版本为其他人发布一个答案。

脚本特性

  • 备份文件日命名,前缀 -YYYY-MM-DD-POSTFIX. 扩展名
  • 档案报告/遗失
  • 以前的备份列表
  • 没有压缩/包含以前的备份;)
  • 可以在 windows/linux 上工作

不管怎样,说到剧本。.虽然看起来很多。.记住这里有多余的。.因此,如果需要,可以随意删除报告部分..。

也可能看起来凌乱,某些东西可以很容易地清理... 所以不要评论它,它只是一个快速脚本与基本的意见扔进来。.不是生活用品。.但容易清理生活使用!

在本例中,它是从位于根 www/public _ html 文件夹中的目录运行的。.所以只需要访问一个文件夹就可以访问根目录。

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

它能做什么?

它将只压缩变量 $pathBase 的完整内容,并将压缩文件存储在同一个文件夹中。它对以前的备份执行一个简单的检测并跳过它们。

CRON 备份

我刚刚在 linux 上测试了这个脚本,它在 cron 作业中使用了 pathBase 的绝对 url,并且运行得很好。

如果你正在读这篇文章,想知道为什么要用 addFile 而不是 addFromString 来压缩文件,但是这并没有用绝对路径来压缩文件(只是压缩文件而已) ,请看我的问题并回答 给你

使用此功能:

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

示例使用:

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

用这个就可以了。

$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;
}

用 PHP 创建一个 zip 文件夹。

压缩创建方法

   public function zip_creation($source, $destination){
$dir = opendir($source);
$result = ($dir === false ? false : true);


if ($result !== false) {


        

$rootPath = realpath($source);
         

// Initialize archive object
$zip = new ZipArchive();
$zipfilename = $destination.".zip";
$zip->open($zipfilename, 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();
        

return TRUE;
} else {
return FALSE;
}




}

调用 zip 方法

$source = $source_directory;
$destination = $destination_directory;
$zipcreation = $this->zip_creation($source, $destination);

包括所有子文件夹:

new GoodZipArchive('path/to/input/folder',    'path/to/output_zip_file.zip') ;

这里是 源代码(可能有一个更新,但下面我把该代码的副本) :

class GoodZipArchive extends ZipArchive
{
public function __construct($a=false, $b=false) { $this->create_func($a, $b);  }
    

public function create_func($input_folder=false, $output_zip_file=false)
{
if($input_folder !== false && $output_zip_file !== false)
{
$res = $this->open($output_zip_file, ZipArchive::CREATE);
if($res === TRUE)   { $this->addDir($input_folder, basename($input_folder)); $this->close(); }
else                { echo 'Could not create a zip archive. Contact Admin.'; }
}
}
    

// Add a Dir with Files and Subdirs to the archive
public function addDir($location, $name) {
$this->addEmptyDir($name);
$this->addDirDo($location, $name);
}


// Add Files & Dirs to archive
private function addDirDo($location, $name) {
$name .= '/';         $location .= '/';
// Read all Files in Dir
$dir = opendir ($location);
while ($file = readdir($dir))    {
if ($file == '.' || $file == '..') continue;
// Rekursiv, If dir: GoodZipArchive::addDir(), else ::File();
$do = (filetype( $location . $file) == 'dir') ? 'addDir' : 'addFile';
$this->$do($location . $file, $name . $file);
}
}
}

如果你有 子文件夹并且你想保留文件夹的结构,这样做:

$zip = new \ZipArchive();
$fileName = "my-package.zip";
if ($zip->open(public_path($fileName), \ZipArchive::CREATE) === true)
{
$files = \Illuminate\Support\Facades\File::allFiles(
public_path('/MY_FOLDER_PATH/')
);


foreach ($files as $file) {
$zip->addFile($file->getPathname(), $file->getRelativePathname());
}


$zip->close();
return response()
->download(public_path($fileName))
->deleteFileAfterSend(true);
}

从服务器中删除文件 my-package.zip

不要忘记用要下载的文件夹的路径更改 /MY_FOLDER_PATH/

如果确定所有操作都正确,但仍然无法正常工作,请检查 PHP (用户)权限。

我的建议是:

class compressor {
    

/**
* public static $NOT_COMPRESS
* use: compressor::$NOT_COMPRESS
* no compress thoses files for upload
*/
public static $NOT_COMPRESS = array(
    

'error_log',
'cgi-bin',
'whatever/whatever'
);
/**
* end public static $NOT_COMPRESS
*/
    

    

/**
* public function compress_folder( $dir, $version, $archive_dest );
* @param  {string}  $dir | absolute path to the directory
* @param  {string}  $version_number | ex: 0.1.1
* @param  {string}  $archive_dest | absolute path to the future compressed file
* @return {void}    DO A COMPRESSION OF A FOLDER
*/
public function compress_folder(  $dir, $version, $archive_dest  ){


    

// name of FUTURE .zip file
$archive_name = $version_number.'.zip';
    

// test dir exits
if( !is_dir($dir) ){ exit('No temp directory ...'); }
    

// Iterate and archive API DIRECTORIES AND FOLDERS
    

// create zip archive + manager
$zip = new ZipArchive;
$zip->open( $archive_dest,
ZipArchive::CREATE | ZipArchive::OVERWRITE );
    

// iterator / SKIP_DOTS -> ignore '..' and '.'
$it = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator( $dir,
RecursiveDirectoryIterator::SKIP_DOTS )
);
    

                

// loop iterator
foreach( $it as $file ){
    

    

// check files not to add for compress
    

// loop list for not add to upload .zip
foreach( compressor::$NOT_COMPRESS as $k => $v) {
    

if( preg_match( '/^('.preg_quote($v,'/').')/', $it->getSubPathName() ) == true ){
    

    

// break this loop and parent loop
continue 2;
}
}
// end loop list
    

// for Test
// echo $it->getSubPathName()."\r\n";
    

// no need to check if is a DIRECTORY with $it->getSubPathName()
// DIRECTORIES are added automatically
$zip->addFile( $it->getPathname(),  $it->getSubPathName() );
    

}
// end  loop
    

$zip->close();
// END Iterate and archive API DIRECTORIES AND FOLDERS
    

}
/**
* public function compress_folder( $version_number );
*/


}
// end class compressor

用途:

// future name of the archive
$version = '0.0.1';


// path of directory to compress
$dir = $_SERVER['DOCUMENT_ROOT'].'/SOURCES';


// real path to FUTURE ARCHIVE
$archive_dest = $_SERVER['DOCUMENT_ROOT'].'/COMPRESSED/'.$version.'.zip';




$Compress = new compressor();
$Compress->compress_folder( $dir, $version, $archive_dest );


// this create a .zip file like :
$_SERVER['DOCUMENT_ROOT'].'/COMPRESSED/0.0.1.zip