Я нашел несколько способов, как сделать ZIP для определенного файла, но как насчет определенной папки?
Folder/
index.html
picture.jpg
important.txt
Внутри папки My Folder находятся файлы. После архивации папки My Folder я также хочу удалить все содержимое папки, кроме important.txt.
Мне нужна ваша помощь. Спасибо.
Ответ 1
Архивация целой папки:
// Получаем реальный путь к нашей папке
$rootPath = realpath('folder-to-zip');
// Инициализация объекта архива
$zip = new ZipArchive();
$zip->open('file.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE);
// Создание рекурсивного итератора каталогов
/** @var SplFileInfo[] $files */
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($rootPath),
RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($files as $name => $file) {
// Пропустите каталоги (они будут добавлены автоматически)
if (!$file->isDir()) {
// Получение реального и относительного пути для текущего файла
$filePath = $file->getRealPath();
$relativePath = substr($filePath, strlen($rootPath) + 1);
// Добавить текущий файл в архив
$zip->addFile($filePath, $relativePath);
}
}
// Zip-архив будет создан только после закрытия объекта
$zip->close();
Архивация папки + удаление всех файлов, кроме "important.txt":
// Инициализация объекта архива
$zip = new ZipArchive();
$zip->open('file.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE);
// Инициализация пустого "списка удаления"
$filesToDelete = array();
// Создание рекурсивного итератора каталогов
/** @var SplFileInfo[] $files */
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($rootPath),
RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($files as $name => $file) {
// Пропустите каталоги (они будут добавлены автоматически)
if (!$file->isDir()) {
// Получение реального и относительного пути для текущего файла
$filePath = $file->getRealPath();
$relativePath = substr($filePath, strlen($rootPath) + 1);
// Добавить текущий файл в архив
$zip->addFile($filePath, $relativePath);
// Добавить текущий файл в "список удаления"
// удалить его позже, потому что ZipArchive создает архив только после вызова функции close, и ZipArchive блокирует файлы до создания архива
if ($file->getFilename() != 'important.txt') {
$filesToDelete[] = $filePath;
}
}
}
// Zip-архив будет создан только после закрытия объекта
$zip->close();
// Удалить все файлы из "списка удаления"
foreach ($filesToDelete as $file) {
unlink($file);
}
Ответ 2
В классе ZipArchive есть полезный недокументированный метод: addGlob();
$zipFile = "./testZip.zip";
$zipArchive = new ZipArchive();
if ($zipArchive->open($zipFile, (ZipArchive::CREATE | ZipArchive::OVERWRITE)) !== true)
die("Ошибка при создании архива\n");
$zipArchive->addGlob("./*.txt");
if ($zipArchive->status != ZIPARCHIVE::ER_OK)
echo "Ошибка при записи файлов в zip\n";
$zipArchive->close();
Ответ 3
$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();
Однако это не будет рекурсивно архивироваться.
Ответ 4
Я попробовал использовать приведенный ниже код, и он работает. Код не требует пояснений.
<?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 'Не удалось создать zip архив!';
}
?>
Ответ 5
Это функция, которая архивирует всю папку и ее содержимое в zip-файл, и вы можете использовать ее просто, например, так :
addzip ("path/folder/" , "/path2/folder.zip" );
И непосредственно реализация:
// сжать все файлы в исходном каталоге в каталог назначения
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";
}
Web