ZipArchive::addEmptyDir
(PHP 5 >= 5.2.0, PECL zip >= 1.8.0)
ZipArchive::addEmptyDir — Add a new directory
Description
bool ZipArchive::addEmptyDir
( string
$dirname
)Adds an empty directory in the archive.
Parameters
-
dirname
-
The directory to add.
Return Values
Returns TRUE
on success or FALSE
on failure.
Examples
Example #1 Create a new directory in an archive
<?php
$zip = new ZipArchive;
if ($zip->open('test.zip') === TRUE) {
if($zip->addEmptyDir('newDirectory')) {
echo 'Created a new root directory';
} else {
echo 'Could not create the directory';
}
$zip->close();
} else {
echo 'failed';
}
?>
- PHP Руководство
- Функции по категориям
- Индекс функций
- Справочник функций
- Расширения для сжатия и архивации
- Zip
- Функция ZipArchive::addEmptyDir() - Добавляет новую директорию
- Функция ZipArchive::addFile() - Добавляет в ZIP-архив файл по указанному пути
- Функция ZipArchive::addFromString() - Добавяет файл в ZIP-архив, используя его содержимое
- Функция ZipArchive::addGlob() - Add files from a directory by glob pattern
- Функция ZipArchive::addPattern() - Add files from a directory by PCRE pattern
- Функция ZipArchive::close() - Закрывает активный архив (открытый или вновь созданный)
- Функция ZipArchive::deleteIndex() - Удаляет элемент в архиве, используя его индекс
- Функция ZipArchive::deleteName() - Удаляет элемент в архиве, используя его имя
- Функция ZipArchive::extractTo() - Извлекает содержимое архива
- Функция ZipArchive::getArchiveComment() - Возвращает комментарий ZIP-архива
- Функция ZipArchive::getCommentIndex() - Возвращает комментарий элемента, используя его индекс
- Функция ZipArchive::getCommentName() - Возвращает комментарий элемента, используя его имя
- Функция ZipArchive::getExternalAttributesIndex() - Retrieve the external attributes of an entry defined by its index
- Функция ZipArchive::getExternalAttributesName() - Retrieve the external attributes of an entry defined by its name
- Функция ZipArchive::getFromIndex() - Возвращает содержимое элемента по его индексу
- Функция ZipArchive::getFromName() - Возвращает содержимое элемента по его имени
- Функция ZipArchive::getNameIndex() - Возвращает имя элемента по его индексу
- Функция ZipArchive::getStatusString() - Возвращают статус сообщения об ошибке, системный и/или zip-статус
- Функция ZipArchive::getStream() - Получить дескриптор файла элемента, определенный по имени элемента (только для чтения)
- Функция ZipArchive::locateName() - Возвращает индекс элемента в архиве
- Функция ZipArchive::open() - Открывает ZIP-архив
- Функция ZipArchive::renameIndex() - Переименовывает элемент по его индексу
- Функция ZipArchive::renameName() - Переименовывает элемент по его имени
- Функция ZipArchive::setArchiveComment() - Устанавливает комментарий к ZIP-архиву
- Функция ZipArchive::setCommentIndex() - Устанавливает комментарий к элементу по его индексу
- Функция ZipArchive::setCommentName() - Устанавливает комментарий к элементу, заданному по имени
- ZipArchive::setCompressionIndex
- ZipArchive::setCompressionName
- Функция ZipArchive::setExternalAttributesIndex() - Set the external attributes of an entry defined by its index
- Функция ZipArchive::setExternalAttributesName() - Set the external attributes of an entry defined by its name
- ZipArchive::setPassword
- Функция ZipArchive::statIndex() - Получение детальной информации о элементе по его индексу
- Функция ZipArchive::statName() - Получение детальной информации о элементе по его имени
- Функция ZipArchive::unchangeAll() - Отменяет все изменения, сделанные в архиве
- Функция ZipArchive::unchangeArchive() - Возвращает все глобальные изменения, сделанные в архиве
- Функция ZipArchive::unchangeIndex() - Отменяет все измения у позиции с заданным индексом
- Функция ZipArchive::unchangeName() - Отменяет все измения у позиции с заданным именем
Коментарии
There is kind of a bug in the method
ZipArchive::addFile
which affects the class ZipFolder below.
It is related to the numer of max filehandles of the OS.
As workaround add a file-counter to the class and close + reopen the archive if a certain number of files (directories count as files!) is reached.
For more details see here:
http://de.php.net/manual/en/function.ziparchive-addfile.php
or go directly here
http://bugs.php.net/bug.php?id=40494
or here
http://pecl.php.net/bugs/bug.php?id=9443
Here's a simple recurring function to add a directory, all sub-directories and all files to an already created zip file;
<?php
// Function to recursively add a directory,
// sub-directories and files to a zip archive
function addFolderToZip($dir, $zipArchive){
if (is_dir($dir)) {
if ($dh = opendir($dir)) {
//Add the directory
$zipArchive->addEmptyDir($dir);
// Loop through all the files
while (($file = readdir($dh)) !== false) {
//If it's a folder, run the function again!
if(!is_file($dir . $file)){
// Skip parent and root directories
if( ($file !== ".") && ($file !== "..")){
addFolderToZip($dir . $file . "/", $zipArchive);
}
}else{
// Add the files
$zipArchive->addFile($dir . $file);
}
}
}
}
}
?>
Would be nice to see more input on these functions :)
Dayjo
addEmptyDir doesn't exist now,
use $zip->addFile($file, $dir.$fichier);
nothing on the net about this,
addEmptyDir work on Ubuntu but not on Debian Etch
I've brought a little modification to dayjo's code, so it wouldn't re-create the whole structure of your working drive in the zip file:
<?php
// Function to recursively add a directory,
// sub-directories and files to a zip archive
function addFolderToZip($dir, $zipArchive, $zipdir = ''){
if (is_dir($dir)) {
if ($dh = opendir($dir)) {
//Add the directory
if(!empty($zipdir)) $zipArchive->addEmptyDir($zipdir);
// Loop through all the files
while (($file = readdir($dh)) !== false) {
//If it's a folder, run the function again!
if(!is_file($dir . $file)){
// Skip parent and root directories
if( ($file !== ".") && ($file !== "..")){
addFolderToZip($dir . $file . "/", $zipArchive, $zipdir . $file . "/");
}
}else{
// Add the files
$zipArchive->addFile($dir . $file, $zipdir . $file);
}
}
}
}
}
?>
If you don't specify the third parameter (zipdir), the directory you're adding will be added at the root of the zip file.
D.Jann
Here's a stack-based way to zip a directory. No recursion, no function, no class:
<?php
$zip = new ZipArchive();
$zip->open('test.zip', ZipArchive::CREATE);
$dirName = 'test';
if (!is_dir($dirName)) {
throw new Exception('Directory ' . $dirName . ' does not exist');
}
$dirName = realpath($dirName);
if (substr($dirName, -1) != '/') {
$dirName.= '/';
}
/*
* NOTE BY danbrown AT php DOT net: A good method of making
* portable code in this case would be usage of the PHP constant
* DIRECTORY_SEPARATOR in place of the '/' (forward slash) above.
*/
$dirStack = array($dirName);
//Find the index where the last dir starts
$cutFrom = strrpos(substr($dirName, 0, -1), '/')+1;
while (!empty($dirStack)) {
$currentDir = array_pop($dirStack);
$filesToAdd = array();
$dir = dir($currentDir);
while (false !== ($node = $dir->read())) {
if (($node == '..') || ($node == '.')) {
continue;
}
if (is_dir($currentDir . $node)) {
array_push($dirStack, $currentDir . $node . '/');
}
if (is_file($currentDir . $node)) {
$filesToAdd[] = $node;
}
}
$localDir = substr($currentDir, $cutFrom);
$zip->addEmptyDir($localDir);
foreach ($filesToAdd as $file) {
$zip->addFile($currentDir . $file, $localDir . $file);
}
}
$zip->close();
?>
Add folder and sub-directories to zip archive.
<?php
$archive_name = "archive.zip"; // name of zip file
$archive_folder = "folder"; // the folder which you archivate
$zip = new ZipArchive;
if ($zip -> open($archive_name, ZipArchive::CREATE) === TRUE)
{
$dir = preg_replace('/[\/]{2,}/', '/', $archive_folder."/");
$dirs = array($dir);
while (count($dirs))
{
$dir = current($dirs);
$zip -> addEmptyDir($dir);
$dh = opendir($dir);
while($file = readdir($dh))
{
if ($file != '.' && $file != '..')
{
if (is_file($file))
$zip -> addFile($dir.$file, $dir.$file);
elseif (is_dir($file))
$dirs[] = $dir.$file."/";
}
}
closedir($dh);
array_shift($dirs);
}
$zip -> close();
echo 'Archiving is sucessful!';
}
else
{
echo 'Error, can\'t create a zip file!';
}
?>
On PHP >5.4, This function will create a file, not a directory.
For instance:
$zip->addEmptyDir ( 'path/to/dir/' );
will create the folders "path/", and "path/to/", and a dummy 0-byte file named "dir" in the latter.
If then we add a file to that dir, say like this:
$zip->addFromString ( 'path/to/dir/file.txt', $data );
the result will be a SEPARATE folder named "dir" next to the dummy "dir" file. The "dir" folder will contain the file "file.txt".
This was tested on an APACHE server running PHP 5.4
I have modified thomas dot rubbert at yahoo dot de a little bit
$uploads_dir =storage_path().'/app/public/files/' ;
if(!file_exists($uploads_dir)){
mkdir($uploads_dir,0777,true);
}
$zip_file=$uploads_dir.'download.zip';
if(file_exists($zip_file)){
unlink($zip_file);
}
$zip = new \ZipArchive();
if (!$zip->open($zip_file, \ZIPARCHIVE::CREATE)) {
http_response_code(501);
echo 'Zip creation failed';
die();
}
$img=$uploads_dir.'img';
$dirName = realpath($img);
if (substr($dirName, -1) != DIRECTORY_SEPARATOR) {
$dirName.= DIRECTORY_SEPARATOR;
}
$dirStack = array($dirName);
//Find the index where the last dir starts
$cutFrom = strrpos(substr($dirName, 0, -1), DIRECTORY_SEPARATOR)+1;
while (!empty($dirStack)) {
$currentDir = array_pop($dirStack);
$filesToAdd = array();
$dir = dir($currentDir);
while (false !== ($node = $dir->read())) {
if (($node == '..') || ($node == '.')) {
continue;
}
if (is_dir($currentDir . $node)) {
array_push($dirStack, $currentDir . $node . DIRECTORY_SEPARATOR);
}
if (is_file($currentDir . $node)) {
$filesToAdd[] = $node;
}
}
$localDir =str_replace(DIRECTORY_SEPARATOR,'/',substr($currentDir, $cutFrom));
$zip->addEmptyDir($localDir);
foreach ($filesToAdd as $file) {
$zip->addFile($currentDir . $file, $localDir . $file);
}
}
// any additional files
$db=$uploads_dir.'databse.db';
//$zip->addFromString(basename($db), file_get_contents($db));
$zip->addFile($db, basename($db));
$zip->close();
The <code>addEmptyDir</code> method does not handle permissions bits and directory <code>mtime</code>. These need to be set separately after the directory has been created in the Zip Archive.
Note that setting the <code>mtime</code> is only available since PHP >= 8.0, so it will stay the current timestamp of the <code>addEmptyDir</code> call with PHP 7.4 and below.
Here is a function to fix both permissions and <code>mtime</code> of a directory in a Zip Archive.
<pre><code lang="php">
function fixDirAttributes(ZipArchive $zip, string $path, string $name)
{
// Gets the index of the directory in the Zip archive
$indexInZip = $zip->locateName('/' === mb_substr($name, -1) ? $name : $name . '/');
if (false !== $indexInZip) { // Name found
if (method_exists($zip, 'setMtimeIndex')) { // PHP >= 8.0.0, PECL zip >= 1.16.0
$zip->setMtimeIndex($indexInZip, filemtime($path)); // Fixes the mtime of the directory
}
$filePerms = fileperms($path); // Gets permissions on the directory
if (false !== $filePerms) { // filePerms supported
$attr = $filePerms << 16; // Left-shift permission to git the external attributes value
$zip->setExternalAttributesIndex($indexInZip, \ZipArchive::OPSYS_UNIX, $attr);
}
}
}
</pre></code>