Как zip всю папку с помощью PHP
Я нашел здесь в stackoveflow некоторые коды о том, как ZIP конкретный файл, но как насчет конкретной папки?
Folder/
index.html
picture.jpg
important.txt
внутри My Folder
есть файлы. после застегивания My Folder
, Я также хочу, чтобы удалить все содержимое папки, кроме important.txt
.
нашел это здесь в стеке
мне нужна ваша помощь. спасибо.
14 ответов:
код обновлен 2015/04/22.
Zip целая папка:
// 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 всю папку + удалить все файлы, кроме " важно.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::OVERWRITE)) 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
попробуйте это:
$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 рекурсивно, хотя.
Я предполагаю, что это работает на сервере, где приложение zip в пути поиска. Должно быть верно для всех unix-серверов, и я думаю, что большинство серверов на базе windows.
exec('zip -r archive.zip "My folder"'); unlink('My\ folder/index.html'); unlink('My\ folder/picture.jpg');
архив будет находиться в архиве.потом застегните молнию. Имейте в виду, что пробелы в именах файлов или папок являются частой причиной ошибок и их следует избегать, когда это возможно.
Я пробовал С ниже код и он работает. Код не требует пояснений, пожалуйста, дайте мне знать если вы имеете любые вопросы.
<?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'; } ?>
это функция, которая застегивает всю папку и ее содержимое в zip-файл, и вы можете использовать его просто так:
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"; }
почему бы не попробовать EFS PhP-ZiP многотомный скрипт ... Я сжал и передал сотни концертов и миллионы файлов ... ssh необходим для эффективного создания архивов.
но я верю, что результирующие файлы могут быть использованы с exec непосредственно из php:
exec('zip -r backup-2013-03-30_0 . -i@backup-2013-03-30_0.txt');
Я не знаю, если это работает. Я не пробовал ...
"секрет" заключается в том, что время выполнения архивации не должно превышать время, допустимое для выполнения PHP кода.
Это рабочий пример создания молнии в PHP:
$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();
использовать эту функцию:
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');
Я сделал некоторые небольшие улучшения в сценарии.
<?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();
Я нашел этот пост в google в качестве второго верхнего результата, сначала использовал exec : (
в любом случае, пока это не мое точно.. Я решил опубликовать ответ для других с моей быстрой, но расширенной версией этого.
ФУНКЦИИ СКРИПТА
- резервное копирование имен файлов день за днем, префикс-гггг-ММ-ДД-постфикс.Расширение
- Файл Отчетности / Отсутствует
- Список Предыдущих Резервных Копий
- не zip / включить предыдущие резервные копии ;)
- работает на 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 и сохранит zip в той же папке. Это простое обнаружение для предыдущих резервных копий и пропускает их.
CRON BACKUP
этот скрипт, который я только что протестировал на linux и отлично работал с заданием cron с использованием абсолютного url-адреса для pathBase.
для тех, кто читает этот пост и ищет, почему zip файлы с помощью addFile вместо addFromString, который не zip файлы с их абсолютным путем (просто молнии файлы и ничего больше), см. мой вопрос и ответ здесь
Use this is working fine. $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; }