如何使用 PHP 压缩整个文件夹
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4914750/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to zip a whole folder using PHP
提问by woninana
I have found here at stackoveflow some codes on how to ZIP a specific file, but how about a specific folder?
我在 stackoveflow 上找到了一些关于如何压缩特定文件的代码,但是特定文件夹呢?
Folder/
index.html
picture.jpg
important.txt
inside in My Folder
, there are files. after zipping the My Folder
, i also want to delete the whole content of the folder except important.txt
.
在 in 里面My Folder
,有文件。压缩后My Folder
,我还想删除文件夹的全部内容,除了important.txt
.
Found this here at stack
在堆栈中找到了这个
I need your help. thanks.
我需要你的帮助。谢谢。
回答by Dador
Code updated 2015/04/22.
代码更新 2015/04/22。
Zip a whole folder:
压缩整个文件夹:
// 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 a whole folder + delete all files except "important.txt":
压缩整个文件夹 + 删除除“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);
}
回答by Mark Baker
There is a useful undocumented method in the ZipArchive class: addGlob();
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();
Now documented at: www.php.net/manual/en/ziparchive.addglob.php
回答by netcoder
Try this:
尝试这个:
$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();
This will notzip recursively though.
但这不会递归压缩。
回答by Kevin Read
I assume this is running on a server where the zip application is in the search path. Should be true for all unix-based and I guess most windows-based servers.
我假设这是在 zip 应用程序位于搜索路径中的服务器上运行。应该适用于所有基于 Unix 的服务器,我猜大多数基于 Windows 的服务器都是如此。
exec('zip -r archive.zip "My folder"');
unlink('My\ folder/index.html');
unlink('My\ folder/picture.jpg');
The archive will reside in archive.zip afterwards. Keep in mind that blanks in file or folder names are a common cause of errors and should be avoided where possible.
之后存档将驻留在 archive.zip 中。请记住,文件或文件夹名称中的空格是导致错误的常见原因,应尽可能避免。
回答by Amir Md Amiruzzaman
I tried with the code below and it is working. The code is self explanatory, please let me know if you have any 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';
}
?>
回答by Alireza Fallah
This is a function that zips a whole folder and its contents in to a zip file and you can use it simple like this :
这是一个将整个文件夹及其内容压缩到一个 zip 文件中的功能,您可以像这样简单地使用它:
addzip ("path/folder/" , "/path2/folder.zip" );
function :
功能 :
// 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";
}
回答by ByREV
Why not Try EFS PhP-ZiP MultiVolume Script... I zipped and transferred hundreds of gigs and millions of files ... ssh is needed to effectively create archives.
为什么不试试EFS PhP-ZiP MultiVolume Script......我压缩并传输了数百个演出和数百万个文件......需要 ssh 来有效地创建档案。
But i belive that resulting files can be used with exec directly from php:
但我相信生成的文件可以直接从 php 与 exec 一起使用:
exec('zip -r backup-2013-03-30_0 . -i@backup-2013-03-30_0.txt');
I do not know if it works. I have not tried ...
我不知道它是否有效。我没试过...
"the secret" is that the execution time for archiving should not exceed the time allowed for execution of PHP code.
“秘诀”是归档的执行时间不应超过 PHP 代码允许执行的时间。
回答by Sun Love
This is a working example of making ZIPs in 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();
回答by Angry 84
I found this post in google as the second top result, first was using exec :(
我在谷歌中发现这篇文章是第二个顶级结果,首先是使用 exec :(
Anyway, while this did not suite my needs exactly.. I decided to post an answer for others with my quick but extended version of this.
无论如何,虽然这并不完全符合我的需求......我决定用我的快速但扩展版本为其他人发布答案。
SCRIPT FEATURES
脚本特性
- Backup file naming day by day, PREFIX-YYYY-MM-DD-POSTFIX.EXTENSION
- File Reporting / Missing
- Previous Backups Listing
- Does not zip / include previous backups ;)
- Works on windows/linux
- 备份文件逐日命名,PREFIX-YYYY-MM-DD-POSTFIX.EXTENSION
- 文件报告/丢失
- 以前的备份列表
- 不压缩/包括以前的备份;)
- 适用于 Windows/Linux
Anyway, onto the script.. While it may look like a lot.. Remember there is excess in here.. So feel free to delete the reporting sections as needed...
无论如何,到脚本上.. 虽然它可能看起来很多.. 请记住这里有多余的.. 所以请根据需要随意删除报告部分......
Also it may look messy as well and certain things could be cleaned up easily... So dont comment about it, its just a quick script with basic comments thrown in.. NOT FOR LIVE USE.. But easy to clean up for live use!
它也可能看起来很乱,某些东西可以很容易地清理......所以不要评论它,它只是一个带有基本评论的快速脚本......不适合实时使用......但易于清理以供实时使用!
In this example, it is run from a directory that is inside of the root www / public_html folder.. So only needs to travel up one folder to get to the root.
在这个例子中,它是从根 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];
}
?>
WHAT DOES IT DO??
它有什么作用??
It will simply zip the complete contents of the variable $pathBase and store the zip in that same folder. It does a simple detection for previous backups and skips them.
它将简单地压缩变量 $pathBase 的完整内容并将 zip 存储在同一文件夹中。它对以前的备份进行简单的检测并跳过它们。
CRON BACKUP
定时备份
This script i've just tested on linux and worked fine from a cron job with using an absolute url for the pathBase.
这个脚本我刚刚在 linux 上测试过,并且在使用 pathBase 的绝对 url 的 cron 作业中运行良好。
回答by Waqar Alamgir
Use this function:
使用这个功能:
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();
}
Example use:
使用示例:
zip('/folder/to/compress/', './compressed.zip');