(PHP 5 >= 5.2.0, PHP 7, PHP 8, PECL zip >= 1.1.0)
ZipArchive::close — Закрывает активный архив (открытый или вновь созданный)
Описание
public ZipArchive::close(): bool
Если архив не содержит файлов, файл полностью удаляется
(пустой архив не записывается).
Список параметров
У этой функции нет параметров.
Возвращаемые значения
Возвращает true
в случае успешного выполнения или false
в случае возникновения ошибки.
jared at kippage dot com ¶
13 years ago
It may seem a little obvious to some but it was an oversight on my behalf.
If you are adding files to the zip file that you want to be deleted make sure you delete AFTER you call the close() function.
If the files added to the object aren't available at save time the zip file will not be created.
john factorial ¶
12 years ago
If you're adding multiple files to a zip and your $zip->close() call is returning FALSE, ensure that all the files you added actually exist. Apparently $zip->addFile() returns TRUE even if the file doesn't actually exist. It's a good idea to check each file with file_exists() or is_readable() before calling $zip->addFile() on it.
javier dot santacruz at avature dot net ¶
6 years ago
ZipArchive.close() changes its behaviour in PHP7. The function ignores directories in PHP5 but fails in PHP7 with:
Unexpected PHP error [ZipArchive::close(): Read error: Is a directory]
The following code works in PHP5 but not in PHP7:
<?php
// test.php
$zip = new ZipArchive();
$zip->open('/tmp/test.zip', ZipArchive::CREATE);
$zip->addFile('.', '.');
$ret = $zip->close();
echo "Closed with: " . ($ret ? "true" : "false") . "n";
?>
For php5:
php --version
PHP 5.5.38-1-avature-ondrej-fork (cli) (built: Aug 31 2016 16:37:38)
php test.php
Closed with: true
For php7:
php --version
PHP 7.0.8-0ubuntu0.16.04.2 (cli) ( NTS )
php test.php
Closed with: false
m021 at springtimesoftware dot com ¶
11 years ago
If you have created a zip file and added a file to it without error, yet the ZipArchive::close call fails (with ER_TMPOPEN: "Failure to create temporary file") and the zip file is not created, check to see if your ZipArchive::open call specifies a pathname containing nonexisting directories. If you expect a containing hierarchy of one or more directories, you must create them yourself before using using ZipArchive. You can write a simple function to recurse using dirname to find each parent directory, creating those that don't exist by using mkdir when leaving the recursion.
luciandex ¶
1 year ago
I am not sure, but seems that $zip->close() can run into errors if the path specified in $zip->open is a relative path, not absolute.
So, when create archives, please specify ABSOLUTE PATH, not relative path for zip file to be created.
gilthans at gmail dot com ¶
15 years ago
Don't forget to check the zip isn't empty, folks - otherwise the zip won't be created at all, and the server will issue no warning!
I used a certain loop to add files to the zip, and struggled with permissions and documentation for hours before I realize the loop ended up adding no file, even though addFile WAS called, but on a non-existent file.
This might be the reason your zips aren't popping up.
valera at creator dot su ¶
8 years ago
Pay attention, that ZipArchive::addFile() only opens file descriptor and does not compress it. And only ZipArchive::close() compress file and it take quite a lot of time. Be careful with timeouts.
webnull dot www at gmail dot com ¶
11 years ago
Please note you must have write permissions to file and directory where the files is placed to save the archive.
Enyby ¶
6 years ago
If you open archive without flags in PHP 5.6 then you can get errors on close:
Warning: ZipArchive::close(): Zip archive inconsistent in
And changes not saved.
You need use flag ZIPARCHIVE::OVERWRITE on $zip->open.
This issue happens for me only in php 5.6. In php 5.4 and before it works without any flags to $zip->open.
I am trying to fix an issue in an auto-zip script for some images, which I wrote a while ago and it worked until now. Everything seems fine until $zip->close();
which gives the following:
<b>Warning</b>: ZipArchive::close(): Read error: No such file or directory in <b></b> on line <b>287</b><br />
I read the docs and some forums and found out that this could happen in one of the following scenarios:
- If no actual files are added to the zip, since PHP 5.6—this could be a likely explanation since I recently upgraded to PHP 5.6. However:
- I check that each file exists before adding it
- I tried to add a dummy non-empty text file to the zip. Adding it to the zip returns true, as does
file_exists()
on the file - When I echo
$zip->numFiles
and it gives a number of at least 1 (when the zip has no files except the dummy)
- If the directory to where the zip needs to be written doesn’t exist or doesn’t have the right permissions: This didn’t appear to be the case, but just to be sure, I wrote a text file to the same folder in the same script and there was no problem
- If there is a problem writing to the temp directory. It’s a bit harder to check this but I have an upload script in the same system that works, and I made sure that there are no disk space problems etc.
Here is the relevant code. Some variables are defined beforehand. Note that I write every problem to my log, and this script doesn’t generate any entries!
$zip_file = 'Project'.$project_id.'.zip';
$zip = new ZipArchive;
if ($zip_result = $zip->open($zip_path.'/'.$zip_file, ZIPARCHIVE::CREATE) !== true) {
echo 'Error creating zip for project: '.$project_id.'. Error code: '.$zip_result;
help::debugLog('Error creating zip for project: '.$project_id.'. Error code: '.$zip_result);
return false;
}
$file_list = array();
foreach ($item_thumbs as $item)
{
$full_thumb_path = $thumb_dir.'/'.$item['thumb'];
if (file_exists($full_thumb_path) and $item['thumb'])
{
$file_added = $zip->addFile($full_thumb_path, basename($item['thumb']));
if (!$file_added)
help::debugLog('Failed to add item thumb to project zip. Project: '.$project_id.', file name: '.$item['thumb']);
else
$file_list[] = $item['thumb'];
}
elseif ($item['thumb']) /* If thumb indicated in DB doesn't exist in file system */
help::debugLog('Item thumb file '.$item['thumb'].' from item: '.$item['id'].' is missing from its indended location: '.$full_thumb_path);
}
/* Added 2016-05-18 -- creates dummy file for the zip listing its contents, important in case zip is empty */
$file_list_path = $zip_path.'/file_list.txt';
if (!($file_list_file = fopen($file_list_path, 'w+')))
help::debugLog('Failed to create list file (intended for zip) for project: '.$project_id);
fwrite($file_list_file, "File list:n");
fwrite($file_list_file, implode("n", $file_list));
if (file_exists($file_list_path))
{
fclose($file_list_file);
if (!$zip->addFile($file_list_path))
help::debugLog('Failed to add list file to project zip for project: '.$project_id);
unlink($file_list_path);
}
else
help::debugLog('Failed to create list file (intended for zip) for project: '.$project_id);
$zip->close(); // line 287
asked May 18, 2016 at 12:19
Turns out the solution was very simple, and it’s actually referred to in the docs (php.net), in one of the comments by Jared at kippage dot com:
It may seem a little obvious to some but it was an oversight on my behalf.
If you are adding files to the zip file that you want to be deleted make sure you delete AFTER you call the close() function.
If the files added to the object aren’t available at save time the zip file will not be created.
(Source: https://www.php.net/manual/en/ziparchive.close.php#93322)
So from my code above, the «dummy» text file is deleted before the zip is closed, necessarily making it that the file doesn’t exist at the time the zip is created.
I had good reason to believe that the zip was created in a temporary location and only moved to the final location on close()
. Turns out this is not the case.
answered May 24, 2016 at 12:58
YnhockeyYnhockey
3,8075 gold badges33 silver badges49 bronze badges
2
Just because this is #1 in Google for the error message, I’m adding another possible issue that causes this exact same error.
If you do not add any files to the zip archive, it doesn’t yet exist, therefore the close() will fail on an empty archive.
eg:
$zip = new ZipArchive;
$zip->open("foo.zip", ZipArchive::CREATE | ZipArchive::OVERWRITE);
$zip->close();
produces:
ERROR: ZipArchive::close(): Can't remove file: No such file or directory
So if you’re looping and adding files, make sure you’ve added something before calling close().
answered Apr 13, 2021 at 19:12
2
As mentioned in Ynhockey’s answer the most probable reason for this is that you’re deleting the file before closing the zip file. One obvious solution is to delete the files after calling $zip->close()
. But here is an alternative.
Instead of doing
$zip->addFile('file.txt', 'file.txt');
unlink('file.txt');
$zip->close(); //gives error!
You can call the addFromString
function and do this instead:
$zip->addFromString(file_get_contents('file.txt'), 'file.txt');
unlink('file.txt');
$zip->close(); //does not give any error!
answered Dec 22, 2022 at 1:52
supersansupersan
5,4342 gold badges42 silver badges61 bronze badges
Check the value of «$full_thumb_path» in the line
$file_added = $zip->addFile($full_thumb_path, basename($item['thumb']));
The value should be a file path and mustn’t be a directory path.
answered Jul 25, 2016 at 1:47
2
Вопрос:
Я пишу сценарий, который должен архивировать папки и файлы внутри, но я не могу понять, как это сделать, если в одной папке есть другая папка. Я объясню на примере, так что нормы работают
Warning: ZipArchive::close(): Read error: Is a directory in /путь до скрипта/public_html/crm/drive/drive.php on line 102
Folder +
File1
File2
And so on (so it works)
But does not want to work like that
Folder +
File1
FOLDER (this does not work)
Вопрос в том, как сделать так, чтобы, если скрипт увидел папку, которую он также загрузил, и если я увидел папку внутри этой папки, она также загружала файлы в папки, соответственно? Вот мой сценарий
if (isset($_POST['createPath'])) {//Check that the button is clicked
$zip = new ZipArchive(); // Create an archive
$zip_name = time().".zip"; // file name
if ($zip->open($zip_name, ZipArchive::CREATE) !== true) { // open file
die ("Could not open archive");//If the file does not open
}
$var = $_POST["pathUpload"];// Array of variables that are passed through the form
foreach ($var as $key_var) {// We process the array in a loop
$iterator = new RecursiveDirectoryIterator($key_var);//There is a recursive search of the file system directories
foreach ($iterator as $key => $value) {// We process an array of files
$path = pathinfo($value);//Check the path or revert the path to the file
if ($path['basename'] == '.' || $path['basename'] == '..') continue;//Check those files that you download if there are points in the files then download
$zip->addFile(realpath($key), $key);//Add the file to the server
}
$zip->close();//Close archive
if (file_exists($zip_name)) {
// Give the file to download
header('Content-type: application/zip', 'charset=utf-8');
header('Content-Disposition: attachment; filename="'.$zip_name.'"');
ob_end_flush();//Buffering since without it nothing will work
readfile($zip_name); //Read the file
unlink($zip_name);//Delete the variable
}
}
}
Лучший ответ:
Ошибка, потому что вы пытаетесь добавить каталог в Zip с помощью метода
// this function only for adding files!
public function addFile ($filename, $localname = null, $start = 0, $length = 0) {}
метод позволяет добавлять каталог
public function addEmptyDir ($dirname) {}
Другая проблема, которую вы имеете, заключается в неправильном использовании итератора каталогов.
// this way only loop on directories in
$iterator = new RecursiveDirectoryIterator($key_var);//There is a recursive search of the file system directories
правильным способом является использование RecursiveIteratorIterator в RecursiveDirectoryIterator – посмотрите параметры в документах.
пример:
// the right way to recursive get list of the file system directories and files
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($key_var, RecursiveDirectoryIterator::SKIP_DOTS), // skip . and ..
RecursiveIteratorIterator::SELF_FIRST,
RecursiveIteratorIterator::CATCH_GET_CHILD // Ignore "Permission denied"
);
поэтому, чтобы заставить его работать, ваш код должен выглядеть так:
<?php
if (isset($_POST['createPath'])) {//Check that the button is clicked
$zip = new ZipArchive(); // Create an archive
$zip_name = time() . ".zip"; // file name
if ($zip->open($zip_name, ZipArchive::CREATE) !== true) { // open file
die ("Could not open archive");//If the file does not open
}
$var = $_POST["pathUpload"];// Array of variables that are passed through the form
foreach ($var as $key_var) {// We process the array in a loop
// There is a recursive search of the file system directories
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($key_var, RecursiveDirectoryIterator::SKIP_DOTS), // skip . and ..
RecursiveIteratorIterator::SELF_FIRST,
RecursiveIteratorIterator::CATCH_GET_CHILD // Ignore "Permission denied"
);
// all directories and subdir
foreach ($iterator as $path => $dir) {
if (!$dir->isDir()) && is_file($path) {
$zip->addFile(realpath($path)); //Add the file to the server
}
if ($dir->isDir()) {
// do nothing
}
}
$zip->close(); //Close archive
if (file_exists($zip_name)) {
// Give the file to download
header('Content-type: application/zip', 'charset=utf-8');
header('Content-Disposition: attachment; filename="' . $zip_name . '"');
ob_end_flush();//Buffering since without it nothing will work
readfile($zip_name); //Read the file
unlink($zip_name);//Delete the variable
}
}
}
счастливое кодирование 🙂
I need to be able to treat zip files programmatically.
In magento 1.9 I was doing :
$zip = new ZipArchive();
if ($zip->open($Zippath) === TRUE)
{
$zip->addFile($Filepath, $Filename);
$zip->addFile($FilepathL, "toto.txt");
$zip->close();
return TRUE; }
How can I do the same in magento 2?
Amit Bera♦
76.4k20 gold badges117 silver badges230 bronze badges
asked Apr 20, 2017 at 10:03
You can do this the same way
$zip = new ZipArchive();
if ($zip->open($Zippath) === TRUE) {
$zip->addFile($Filepath, $Filename);
$zip->addFile($Filepath, "toto.txt");
$zip->close();
return TRUE;
}
answered Apr 20, 2017 at 10:11
PriyankPriyank
7,4927 gold badges34 silver badges68 bronze badges
2
Alternativaly you can use the Magento framework class of M2 called MagentoFrameworkArchiveZip
and call the pack()
method.
For example, if you injected the class and assigned it to the $zipArchive
variable you can do:
$this->zipArchive->pack($source, $destination);
answered Apr 20, 2017 at 10:18
3
Its basically a php class
. It has nothing to do with Magento. However you can check the implementation is still like the same.
Here is the class http://php.net/manual/en/class.ziparchive.php
And here is the implementation in Magento2.
If you open
libinternalMagentoFrameworkArchiveZip.php you will find this
public function pack($source, $destination)
{
$zip = new ZipArchive();
$zip->open($destination, ZipArchive::CREATE);
$zip->addFile($source);
$zip->close();
return $destination;
}
answered Apr 20, 2017 at 10:15
Kingshuk DebKingshuk Deb
1,2072 gold badges11 silver badges31 bronze badges
Many times, if you repeat and repeat the program (for exemple with F5), the system gives an error message that can not close the temporary file.
Fatal error: Uncaught exception ‘PhpOfficePhpWordExceptionException’ with message ‘Could not close zip file C:UserssongokuAppDataLocalTempPhp9D8B.tmp.’ in C:xampphtdocszdocsrcPhpWordSharedZipArchive.php:163 Stack trace: #0 C:xampphtdocszdocsrcPhpWordTemplateProcessor.php(412): PhpOfficePhpWordSharedZipArchive->close() #1 C:xampphtdocszdocsrcPhpWordTemplateProcessor.php(430): PhpOfficePhpWordTemplateProcessor->save() #2 C:xampphtdocszdocS07c.php(63): PhpOfficePhpWordTemplateProcessor->saveAs(‘reporting/outpu. ‘) #3
Any idea how I can solve this situation ?
Thanks for you help.
Carles
Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.
The text was updated successfully, but these errors were encountered:
If you change zip engine, it seems like you run many times and it doesn’t break
I make this exchange in the configuration
Settings::setZipClass( ‘PclZip’ );
but file.docx is corrupt
I write in ZipArchive.php, method Close() (+-line 162) the next:
Then execute and this is the output
ERROR: Renaming temporary file failed: Invalid argument
Fatal error: Uncaught exception ‘PhpOfficePhpWordExceptionException’ with message ‘Could not close zip file C:UserssongokuAppDataLocalTempPhpDF2F.tmp.’ in C:xampphtdocszdocsrcPhpWordSharedZipArchive.php:164 Stack trace: #0 C:xampphtdocszdocsrcPhpWordTemplateProcessor.php(426): PhpOfficePhpWordSharedZipArchive->close() #1 C:xampphtdocszdocsrcPhpWordTemplateProcessor.php(448): PhpOfficePhpWordTemplateProcessor->save() #2 C:xampphtdocszdocS07d.php(44): PhpOfficePhpWordTemplateProcessor->saveAs(‘reporting/outpu. ‘) #3
thrown in C:xampphtdocszdocsrcPhpWordSharedZipArchive.php on line 164
The code is based in samples -> Sample_07_TemplateCloneRow.php
Finally i tried with phpword.ini
I read this issues but i can not find the correct solution.
Источник
The ZipArchive class
(PHP 5 >= 5.2.0, PHP 7, PHP 8, PECL zip >= 1.1.0)
Introduction
A file archive, compressed with Zip.
Class synopsis
Properties
Index value of last added entry (file or directory). Available as of PHP 8.0.0 and PECL zip 1.18.0.
Status of the Zip Archive. Available for closed archive, as of PHP 8.0.0 and PECL zip 1.18.0.
System status of the Zip Archive. Available for closed archive, as of PHP 8.0.0 and PECL zip 1.18.0.
Number of files in archive
File name in the file system
Comment for the archive
Table of Contents
- ZipArchive::addEmptyDir — Add a new directory
- ZipArchive::addFile — Adds a file to a ZIP archive from the given path
- ZipArchive::addFromString — Add a file to a ZIP archive using its contents
- ZipArchive::addGlob — Add files from a directory by glob pattern
- ZipArchive::addPattern — Add files from a directory by PCRE pattern
- ZipArchive::clearError — Clear the status error message, system and/or zip messages
- ZipArchive::close — Close the active archive (opened or newly created)
- ZipArchive::count — Counts the number of files in the archive
- ZipArchive::deleteIndex — Delete an entry in the archive using its index
- ZipArchive::deleteName — Delete an entry in the archive using its name
- ZipArchive::extractTo — Extract the archive contents
- ZipArchive::getArchiveComment — Returns the Zip archive comment
- ZipArchive::getCommentIndex — Returns the comment of an entry using the entry index
- ZipArchive::getCommentName — Returns the comment of an entry using the entry name
- 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 — Returns the entry contents using its index
- ZipArchive::getFromName — Returns the entry contents using its name
- ZipArchive::getNameIndex — Returns the name of an entry using its index
- ZipArchive::getStatusString — Returns the status error message, system and/or zip messages
- ZipArchive::getStream — Get a file handler to the entry defined by its name (read only)
- ZipArchive::getStreamIndex — Get a file handler to the entry defined by its index (read only)
- ZipArchive::getStreamName — Get a file handler to the entry defined by its name (read only)
- ZipArchive::isCompressionMethodSupported — Check if a compression method is supported by libzip
- ZipArchive::isEncryptionMethodSupported — Check if a encryption method is supported by libzip
- ZipArchive::locateName — Returns the index of the entry in the archive
- ZipArchive::open — Open a ZIP file archive
- ZipArchive::registerCancelCallback — Register a callback to allow cancellation during archive close.
- ZipArchive::registerProgressCallback — Register a callback to provide updates during archive close.
- ZipArchive::renameIndex — Renames an entry defined by its index
- ZipArchive::renameName — Renames an entry defined by its name
- ZipArchive::replaceFile — Replace file in ZIP archive with a given path
- ZipArchive::setArchiveComment — Set the comment of a ZIP archive
- ZipArchive::setCommentIndex — Set the comment of an entry defined by its index
- ZipArchive::setCommentName — Set the comment of an entry defined by its name
- ZipArchive::setCompressionIndex — Set the compression method of an entry defined by its index
- ZipArchive::setCompressionName — Set the compression method of an entry defined by its name
- ZipArchive::setEncryptionIndex — Set the encryption method of an entry defined by its index
- ZipArchive::setEncryptionName — Set the encryption method of an entry defined by its name
- 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::setMtimeIndex — Set the modification time of an entry defined by its index
- ZipArchive::setMtimeName — Set the modification time of an entry defined by its name
- ZipArchive::setPassword — Set the password for the active archive
- ZipArchive::statIndex — Get the details of an entry defined by its index
- ZipArchive::statName — Get the details of an entry defined by its name
- ZipArchive::unchangeAll — Undo all changes done in the archive
- ZipArchive::unchangeArchive — Revert all global changes done in the archive
- ZipArchive::unchangeIndex — Revert all changes done to an entry at the given index
- ZipArchive::unchangeName — Revert all changes done to an entry with the given name
User Contributed Notes 15 notes
Zip a folder (include itself).
Usage:
HZip::zipDir(‘/path/to/sourceDir’, ‘/path/to/out.zip’);
class HZip
<
/**
* Add files and sub-directories in a folder to zip file.
* @param string $folder
* @param ZipArchive $zipFile
* @param int $exclusiveLength Number of text to be exclusived from the file path.
*/
private static function folderToZip ( $folder , & $zipFile , $exclusiveLength ) <
$handle = opendir ( $folder );
while ( false !== $f = readdir ( $handle )) <
if ( $f != ‘.’ && $f != ‘..’ ) <
$filePath = » $folder / $f » ;
// Remove prefix from file path before add to zip.
$localPath = substr ( $filePath , $exclusiveLength );
if ( is_file ( $filePath )) <
$zipFile -> addFile ( $filePath , $localPath );
> elseif ( is_dir ( $filePath )) <
// Add sub-directory.
$zipFile -> addEmptyDir ( $localPath );
self :: folderToZip ( $filePath , $zipFile , $exclusiveLength );
>
>
>
closedir ( $handle );
>
/**
* Zip a folder (include itself).
* Usage:
* HZip::zipDir(‘/path/to/sourceDir’, ‘/path/to/out.zip’);
*
* @param string $sourcePath Path of directory to be zip.
* @param string $outZipPath Path of output zip file.
*/
public static function zipDir ( $sourcePath , $outZipPath )
<
$pathInfo = pathInfo ( $sourcePath );
$parentPath = $pathInfo [ ‘dirname’ ];
$dirName = $pathInfo [ ‘basename’ ];
$z = new ZipArchive ();
$z -> open ( $outZipPath , ZIPARCHIVE :: CREATE );
$z -> addEmptyDir ( $dirName );
self :: folderToZip ( $sourcePath , $z , strlen ( » $parentPath /» ));
$z -> close ();
>
>
?>
With PHP 5.6+, you may come up with theses errors.
Warning: Unknown: Cannot destroy the zip context in Unknown on line 0
Warning: ZipArchive::close(): Can’t remove file: No such file or directory in xxxx.php on line xx
Warning: Unknown: Cannot destroy the zip context in Unknown on line 0
= new ZipArchive ;
$za -> open ( ’51-n.com.zip’ , ZipArchive :: CREATE | ZipArchive :: OVERWRITE );
?>
Warning: ZipArchive::close(): Can’t remove file: No such file or directory in xxxx.php on line xx
= new ZipArchive ;
$za -> open ( ’51-n.com.zip’ , ZipArchive :: CREATE | ZipArchive :: OVERWRITE );
$za -> close ();
?>
It happens when the zip archive is empty.
Your zip archive will not be saved on disk unless it has at least one file. What’s more, when ZipArchive::OVERWRITE is applied, if there exists a file with the same name, it will be removed after ZipArchive::open() is called.
So, don’t forget to put at least one file to your zip archive.
= new ZipArchive ;
$za -> open ( ’51-n.com.zip’ , ZipArchive :: CREATE | ZipArchive :: OVERWRITE );
$za -> addFromString ( ‘wuxiancheng.cn.txt’ , ‘yes’ );
$za -> close ();
?>
There is a usefull function to get the ZipArchive status as a human readable string :
function ZipStatusString ( $status )
<
switch( (int) $status )
<
case ZipArchive :: ER_OK : return ‘N No error’ ;
case ZipArchive :: ER_MULTIDISK : return ‘N Multi-disk zip archives not supported’ ;
case ZipArchive :: ER_RENAME : return ‘S Renaming temporary file failed’ ;
case ZipArchive :: ER_CLOSE : return ‘S Closing zip archive failed’ ;
case ZipArchive :: ER_SEEK : return ‘S Seek error’ ;
case ZipArchive :: ER_READ : return ‘S Read error’ ;
case ZipArchive :: ER_WRITE : return ‘S Write error’ ;
case ZipArchive :: ER_CRC : return ‘N CRC error’ ;
case ZipArchive :: ER_ZIPCLOSED : return ‘N Containing zip archive was closed’ ;
case ZipArchive :: ER_NOENT : return ‘N No such file’ ;
case ZipArchive :: ER_EXISTS : return ‘N File already exists’ ;
case ZipArchive :: ER_OPEN : return ‘S Can’t open file’ ;
case ZipArchive :: ER_TMPOPEN : return ‘S Failure to create temporary file’ ;
case ZipArchive :: ER_ZLIB : return ‘Z Zlib error’ ;
case ZipArchive :: ER_MEMORY : return ‘N Malloc failure’ ;
case ZipArchive :: ER_CHANGED : return ‘N Entry has been changed’ ;
case ZipArchive :: ER_COMPNOTSUPP : return ‘N Compression method not supported’ ;
case ZipArchive :: ER_EOF : return ‘N Premature EOF’ ;
case ZipArchive :: ER_INVAL : return ‘N Invalid argument’ ;
case ZipArchive :: ER_NOZIP : return ‘N Not a zip archive’ ;
case ZipArchive :: ER_INTERNAL : return ‘N Internal error’ ;
case ZipArchive :: ER_INCONS : return ‘N Zip archive inconsistent’ ;
case ZipArchive :: ER_REMOVE : return ‘S Can’t remove file’ ;
case ZipArchive :: ER_DELETED : return ‘N Entry has been deleted’ ;
default: return sprintf ( ‘Unknown status %s’ , $status );
>
>
Simple class xZip to zip big folders into multiple parts and unzip multi zip files at once.
class xZip <
public function __construct () <>
private function _rglobRead ( $source , & $array = array()) <
if (! $source || trim ( $source ) == «» ) <
$source = «.» ;
>
foreach ((array) glob ( $source . «/*/» ) as $key => $value ) <
$this -> _rglobRead ( str_replace ( «//» , «/» , $value ), $array );
>
foreach ((array) glob ( $source . «*.*» ) as $key => $value ) <
$array [] = str_replace ( «//» , «/» , $value );
>
>
private function _zip ( $array , $part , $destination ) <
$zip = new ZipArchive ;
@ mkdir ( $destination , 0777 , true );
if ( $zip -> open ( str_replace ( «//» , «/» , » < $destination >/partz < $part >.zip» ), ZipArchive :: CREATE )) <
foreach ((array) $array as $key => $value ) <
$zip -> addFile ( $value , str_replace (array( «../» , «./» ), NULL , $value ));
>
$zip -> close ();
>
>
public function zip ( $limit = 500 , $source = NULL , $destination = «./» ) <
if (! $destination || trim ( $destination ) == «» ) <
$destination = «./» ;
>
$this -> _rglobRead ( $source , $input );
$maxinput = count ( $input );
$splitinto = (( $maxinput / $limit ) > round ( $maxinput / $limit , 0 )) ? round ( $maxinput / $limit , 0 ) + 1 : round ( $maxinput / $limit , 0 );
for( $i = 0 ; $i $splitinto ; $i ++) <
$this -> _zip ( array_slice ( $input , ( $i * $limit ), $limit , true ), $i , $destination );
>
unset( $input );
return;
>
public function unzip ( $source , $destination ) <
@ mkdir ( $destination , 0777 , true );
foreach ((array) glob ( $source . «/*.zip» ) as $key => $value ) <
$zip = new ZipArchive ;
if ( $zip -> open ( str_replace ( «//» , «/» , $value )) === true ) <
$zip -> extractTo ( $destination );
$zip -> close ();
>
>
>
public function __destruct () <>
>
//$zip = new xZip;
//$zip->zip(500, «images/», «images_zip/»);
//$zip->unzip(«images_zip/», «images/»);
?>
The following code can be used to get a list of all the file names in a zip file.
$za -> open ( ‘theZip.zip’ );
for( $i = 0 ; $i $za -> numFiles ; $i ++ ) <
$stat = $za -> statIndex ( $i );
print_r ( basename ( $stat [ ‘name’ ] ) . PHP_EOL );
>
?>
A way of zipping files and downloading them thereafter:
= array( ‘image.jpeg’ , ‘text.txt’ , ‘music.wav’ );
$zipname = ‘enter_any_name_for_the_zipped_file.zip’ ;
$zip = new ZipArchive ;
$zip -> open ( $zipname , ZipArchive :: CREATE );
foreach ( $files as $file ) <
$zip -> addFile ( $file );
>
$zip -> close ();
///Then download the zipped file.
header ( ‘Content-Type: application/zip’ );
header ( ‘Content-disposition: attachment; filename=’ . $zipname );
header ( ‘Content-Length: ‘ . filesize ( $zipname ));
readfile ( $zipname );
There is a limit withing PHP 5.3.3 (which seems to have been addressed in later versions; 5.3.29 seems ok on a different server).
If you try to open a zip file with more than 65,535 files in it (in my case it had 237,942 files) then you cannot access the later files. The numFiles property only reports the first 65k files.
Read a file from an archive to a variable.
A warning is printed automatically in case of a CRC32 mismatch, which we capture, so we can print our own error message.
= new ZipArchive ();
if ( $zip -> open ( ‘archive.zip’ )) <
$fp = $zip -> getStream ( ‘myfile.txt’ ); //file inside archive
if(! $fp )
die( «Error: can’t get stream to zipped file» );
$stat = $zip -> statName ( ‘myfile.txt’ );
$buf = «» ; //file buffer
ob_start (); //to capture CRC error message
while (! feof ( $fp )) <
$buf .= fread ( $fp , 2048 ); //reading more than 2156 bytes seems to disable internal CRC32 verification (bug?)
>
$s = ob_get_contents ();
ob_end_clean ();
if( stripos ( $s , «CRC error» ) != FALSE ) <
echo ‘CRC32 mismatch, current ‘ ;
printf ( «%08X» , crc32 ( $buf )); //current CRC
echo ‘, expected ‘ ;
printf ( «%08X» , $stat [ ‘crc’ ]); //expected CRC
>
fclose ( $fp );
$zip -> close ();
//Done, unpacked file is stored in $buf
>
?>
To create a corrupt file, change a byte in a zip file using a hex editor.
Hi there.
I just wrote a little function to zip a whole folder while maintaining the dir-structure. I hope it might help someone.
function folderToZip ( $folder , & $zipFile , $subfolder = null ) <
if ( $zipFile == null ) <
// no resource given, exit
return false ;
>
// we check if $folder has a slash at its end, if not, we append one
$folder .= end ( str_split ( $folder )) == «/» ? «» : «/» ;
$subfolder .= end ( str_split ( $subfolder )) == «/» ? «» : «/» ;
// we start by going through all files in $folder
$handle = opendir ( $folder );
while ( $f = readdir ( $handle )) <
if ( $f != «.» && $f != «..» ) <
if ( is_file ( $folder . $f )) <
// if we find a file, store it
// if we have a subfolder, store it there
if ( $subfolder != null )
$zipFile -> addFile ( $folder . $f , $subfolder . $f );
else
$zipFile -> addFile ( $folder . $f );
> elseif ( is_dir ( $folder . $f )) <
// if we find a folder, create a folder in the zip
$zipFile -> addEmptyDir ( $f );
// and call the function again
folderToZip ( $folder . $f , $zipFile , $f );
>
>
>
>
?>
Use it like this:
= new ZipArchive ();
$z -> open ( «test.zip» , ZIPARCHIVE :: CREATE );
folderToZip ( «storeThisFolder» , $z );
$z -> close ();
?>
Have a good day!
Here is a simple function which zips folders with all sub folders or only a simple file. the $data var can be a string or an array.
public function un_zip ( $data , $arcpf , $mode = ‘zip’ , $obj = » ) <
$absoluterpfad = ‘YOUR_BASE_PATH’ ;
$arcpf = $absoluterpfad . DS . $arcpf ;
if( is_object ( $obj )== false ) <
$archiv = new ZipArchive ();
$archiv -> open ( $arcpf , ZipArchive :: CREATE );
>else < $archiv =& $obj ;>
if( $mode == ‘zip’ ) <
if( is_array ( $data )== true ) <
foreach( $data as $dtmp ) <
$archiv =& un_zip ( $dtmp , $arcpf , ‘zip’ ,& $archiv );
>
>else <
if( is_dir ( $data )== true ) <
$archiv -> addEmptyDir ( str_replace ( $absoluterpfad . DS , » , $data ));
$files = scandir ( $data );
$bad = array( ‘.’ , ‘..’ );
$files = array_diff ( $files , $bad );
foreach( $files as $ftmp ) <
if( is_dir ( $data . DS . $ftmp )== true ) <
$archiv -> addEmptyDir ( str_replace ( $absoluterpfad . DS , » , $data . ‘/’ . $ftmp ));
$archiv =& un_zip ( $data . DS . $ftmp , $arcpf , ‘zip’ ,& $archiv );
>elseif( is_file ( $data . DS . $ftmp )== true ) <
$archiv -> addFile ( $data . DS . $ftmp , str_replace ( $absoluterpfad . DS , » , $data . ‘/’ . $ftmp ));
>
>
>elseif( is_file ( $data )== true ) < $archiv ->addFile ( $data , str_replace ( $absoluterpfad . DS , » , $data ));>
>
>
if( is_object ( $obj )== false ) < $archiv ->close ();>
else
if( $mode == ‘unzip’ ) < $archiv ->extractTo ( $data );>
>
?>
3,6GB to be correct) of zip files, this class will generate corrupt files of the result is larger than 4 GB. Using tar.gz is a proper alternative.
You can check general purpose flag to test if the zip file is encrypted. Example function below.
/**
* Check if the file is encrypted
*
* Notice: if file doesn’t exists or cannot be opened, function
* also return false.
*
* @param string $pathToArchive
* @return boolean return true if file is encrypted
*/
function isEncryptedZip ( $pathToArchive ) <
$fp = @ fopen ( $pathToArchive , ‘r’ );
$encrypted = false ;
if ( $fp && fseek ( $fp , 6 ) == 0 ) <
$string = fread ( $fp , 2 );
if ( false !== $string ) <
$data = unpack ( «vgeneral» , $string );
$encrypted = $data [ ‘general’ ] & 0x01 ? true : false ;
>
fclose ( $fp );
>
return $encrypted ;
>
Be wary that there are several algorithms to generate a zip file. I found that Office OpenXML files created with ZipArchive are not recognized by Excel 2007, for example.
You have to use a different class to zip in this case, such as PclZip.
How to detect corrupt files with CRC mismatch:
Creating a corrupt archive for testing is simple — zip some files and change a byte with a hex editor in the resulting ZIP file. Now you can test the file with a ZIP application to learn which file inside the archive is corrupt.
ZipArchive seems unable to detect broken files. ZipArchive::CHECKCONS doesn’t help, only if it’s not a ZIP file at all. It happily decompressed corrupt files in my tests and the user downloading the data is not informed.
Источник
Я пытаюсь исправить проблему в скрипте автоматического архивирования для некоторых изображений, который я написал некоторое время назад и работал до сих пор. Кажется, все в порядке, пока $zip->close();
не выдаст следующее:
<b>Warning</b>: ZipArchive::close(): Read error: No such file or directory in <b></b> on line <b>287</b><br />
Я прочитал документы и некоторые форумы и обнаружил, что это может произойти в одном из следующих сценариев:
- Если в zip-архив не добавлены никакие файлы, начиная с PHP 5.6, это могло быть вероятным объяснением, поскольку я недавно обновился до PHP 5.6. Тем не мение:
- Я проверяю наличие каждого файла перед его добавлением.
- Я попытался добавить в ZIP-файл фиктивный непустой текстовый файл. Добавление его в zip возвращает значение true, как и
file_exists()
в файле - Когда я повторяю
$zip->numFiles
, и он дает число не менее 1 (когда в zip-архиве нет файлов, кроме фиктивного)
- Если каталог, в который нужно записать zip-архив, не существует или не имеет необходимых разрешений: похоже, это не так, но на всякий случай я записал текстовый файл в ту же папку в тот же сценарий и проблем не было
- Если есть проблема с записью во временный каталог. Это немного сложнее проверить, но у меня есть сценарий загрузки в той же системе, которая работает, и я убедился, что нет проблем с дисковым пространством и т. Д.
Вот соответствующий код. Некоторые переменные определены заранее. Обратите внимание, что я записываю все проблемы в свой журнал, и этот сценарий не создает никаких записей!
$zip_file = 'Project'.$project_id.'.zip';
$zip = new ZipArchive;
if ($zip_result = $zip->open($zip_path.'/'.$zip_file, ZIPARCHIVE::CREATE) !== true) {
echo 'Error creating zip for project: '.$project_id.'. Error code: '.$zip_result;
help::debugLog('Error creating zip for project: '.$project_id.'. Error code: '.$zip_result);
return false;
}
$file_list = array();
foreach ($item_thumbs as $item)
{
$full_thumb_path = $thumb_dir.'/'.$item['thumb'];
if (file_exists($full_thumb_path) and $item['thumb'])
{
$file_added = $zip->addFile($full_thumb_path, basename($item['thumb']));
if (!$file_added)
help::debugLog('Failed to add item thumb to project zip. Project: '.$project_id.', file name: '.$item['thumb']);
else
$file_list[] = $item['thumb'];
}
elseif ($item['thumb']) /* If thumb indicated in DB doesn't exist in file system */
help::debugLog('Item thumb file '.$item['thumb'].' from item: '.$item['id'].' is missing from its indended location: '.$full_thumb_path);
}
/* Added 2016-05-18 -- creates dummy file for the zip listing its contents, important in case zip is empty */
$file_list_path = $zip_path.'/file_list.txt';
if (!($file_list_file = fopen($file_list_path, 'w+')))
help::debugLog('Failed to create list file (intended for zip) for project: '.$project_id);
fwrite($file_list_file, "File list:n");
fwrite($file_list_file, implode("n", $file_list));
if (file_exists($file_list_path))
{
fclose($file_list_file);
if (!$zip->addFile($file_list_path))
help::debugLog('Failed to add list file to project zip for project: '.$project_id);
unlink($file_list_path);
}
else
help::debugLog('Failed to create list file (intended for zip) for project: '.$project_id);
$zip->close(); // line 287
2 ответа
Лучший ответ
Оказывается, решение было очень простым, и на самом деле оно упоминается в документации (php.net) в одном из комментариев:
Некоторым это может показаться немного очевидным, но с моей стороны это был недосмотр.
Если вы добавляете файлы в zip-файл, который хотите удалить, убедитесь, что вы удалили ПОСЛЕ вызова функции close ().
Если файлы, добавленные к объекту, недоступны во время сохранения, zip-файл не будет создан.
(Источник: https://www.php.net/manual/en /ziparchive.close.php#93322)
Итак, из моего кода, приведенного выше, «фиктивный» текстовый файл удаляется перед закрытием zip-архива, что обязательно означает, что файл не существует на момент создания zip-архива.
У меня были веские основания полагать, что zip-архив был создан во временном месте и перемещен в последнее место только close()
. Оказывается, это не так.
16
Community
20 Июн 2020 в 09:12
Проверьте значение «$ full_thumb_path» в строке
$file_added = $zip->addFile($full_thumb_path, basename($item['thumb']));
Значением должен быть путь к файлу, а не путь к каталогу.
-1
Daniel Qi
25 Июл 2016 в 01:47
-
#1
When setting the hosting type to «forwarding» and then create a backup the error will be:
backup_restore_helper utility returned incorrect result. Web settings, composer instances, scheduled tasks and database users have not been dumped. Please, contact your service provider
Switching back the hosting type to «web hosting» and then create a backup everything is fine.
OS Ubuntu 14.04.3 LTS
Plesk version 12.5.30 Update #8, last updated at Oct 29, 2015 04:51 AM
-
#2
Same issue here. Seems to be a bug, because it was introduced with the latest update. Before everything went fine.
-
#3
Yes, looks like bug in product. Bug is reported (PPP-18396).
Thank you for your attention.
Last edited: Oct 30, 2015
-
#4
In addition to forwards that don’t work, this also applies to domains without hosting (for example, domains used for only mail).
-
#5
Hello. Problem is fixed in Update #10. It will be available on Monday.
-
#7
<?xml version=»1.0″ encoding=»UTF-8″?>
<execution-result status=»warnings» log-location=»/usr/local/psa/PMM/sessions/2015-11-26-011303.221/migration.result»>
<object name=»server» type=»server»>
<message id=»f0ec486c-18ee-44fc-8984-fb1c3ae9d76b» severity=»warning» code=»UtilityError»>
<description>backup_restore_helper utility returned incorrect result. Web settings, scheduled tasks have not been dumped. Please, contact your service provider</description>
</message>
</object>
</execution-result>
Issue still outstading. Running Plesk 12.5.30 Update #12. Centos 6.7. Not forwarding domains. (just 2 simple plain stright forward domains)
-
#8
confirmed. Issue still not solved with Update #13.
-
#9
In my current environment (12.5.30 Update #13) i cant reproduce this bug.
-
#10
Hello,
happy forums
Plesk Onyx Version 17.0.17 Update #9
I get the following error message on:
Backup Manager
Warning: server «server»
backup_restore_helper utility returned incorrect result. Extension with ID 5 cannot be backuped. Please, contact your service provider
thank you for your help.
-
#11
Hello, Nazmi_Aytekin.
Could you please post output of the following command ‘/usr/local/psa/bin/sw-engine-pleskrun /usr/local/psa/admin/sbin/backup_restore_helper —backup-extension 5 -object-type server’
-
#12
I have the same problem with Onyx 17.0.17 Update #12 on a Debian 8.6:
[[email protected]]:~$ /usr/local/psa/bin/sw-engine-pleskrun /usr/local/psa/admin/sbin/backup_restore_helper —backup-extension 6 -object-type server
PHP Warning: ZipArchive::close(): Read error: Is a directory; File: /opt/psa/admin/plib/Extension/Driver.php, Line: 270
Error occured while sending feedback. HTTP code returned: 502
Error occured while sending feedback. HTTP code returned: 502
Unable to write destination file.
-
#13
Hello,
happy forums
Plesk Onyx Version 17.0.17 Update #9
I get the following error message on:
Backup Manager
Warning: server «server»
backup_restore_helper utility returned incorrect result. Extension with ID 5 cannot be backuped. Please, contact your service providerthank you for your help.
Hi,
Plesk confirmed bug : PPPM-5480
In my case there was a problem with ext. 12 (backup_restore_helper utility returned incorrect result. Extension with ID 12 cannot be backuped. Please, contact your service provider)
-
#14
Hello, Nazmi_Aytekin.
Could you please post output of the following command ‘/usr/local/psa/bin/sw-engine-pleskrun /usr/local/psa/admin/sbin/backup_restore_helper —backup-extension 5 -object-type server’
/usr/local/psa/bin/sw-engine-pleskrun /usr/local/psa/admin/sb in/backup_restore_helper —backup-extension 5 -object-type server
PHP Warning: ZipArchive::close(): Read error: Is a directory; File: /usr/local/p sa/admin/plib/Extension/Driver.php, Line: 270
Error occured while sending feedback. HTTP code returned: 502
Error occured while sending feedback. HTTP code returned: 502
Unable to write destination file.
Коментарии
Don't forget to check the zip isn't empty, folks - otherwise the zip won't be created at all, and the server will issue no warning!
I used a certain loop to add files to the zip, and struggled with permissions and documentation for hours before I realize the loop ended up adding no file, even though addFile WAS called, but on a non-existent file.
This might be the reason your zips aren't popping up.
2007-10-22 14:16:53
http://php5.kiev.ua/manual/ru/ziparchive.close.html
It may seem a little obvious to some but it was an oversight on my behalf.
If you are adding files to the zip file that you want to be deleted make sure you delete AFTER you call the close() function.
If the files added to the object aren't available at save time the zip file will not be created.
2009-09-02 21:08:13
http://php5.kiev.ua/manual/ru/ziparchive.close.html
If you're adding multiple files to a zip and your $zip->close() call is returning FALSE, ensure that all the files you added actually exist. Apparently $zip->addFile() returns TRUE even if the file doesn't actually exist. It's a good idea to check each file with file_exists() or is_readable() before calling $zip->addFile() on it.
2010-12-29 14:58:31
http://php5.kiev.ua/manual/ru/ziparchive.close.html
If you have created a zip file and added a file to it without error, yet the ZipArchive::close call fails (with ER_TMPOPEN: "Failure to create temporary file") and the zip file is not created, check to see if your ZipArchive::open call specifies a pathname containing nonexisting directories. If you expect a containing hierarchy of one or more directories, you must create them yourself before using using ZipArchive. You can write a simple function to recurse using dirname to find each parent directory, creating those that don't exist by using mkdir when leaving the recursion.
2011-05-19 16:14:38
http://php5.kiev.ua/manual/ru/ziparchive.close.html
Pay attention, that ZipArchive::addFile() only opens file descriptor and does not compress it. And only ZipArchive::close() compress file and it take quite a lot of time. Be careful with timeouts.
2014-08-08 04:22:19
http://php5.kiev.ua/manual/ru/ziparchive.close.html
ZipArchive.close() changes its behaviour in PHP7. The function ignores directories in PHP5 but fails in PHP7 with:
Unexpected PHP error [ZipArchive::close(): Read error: Is a directory]
The following code works in PHP5 but not in PHP7:
<?php
// test.php
$zip = new ZipArchive();
$zip->open('/tmp/test.zip', ZipArchive::CREATE);
$zip->addFile('.', '.');
$ret = $zip->close();
echo "Closed with: " . ($ret ? "true" : "false") . "n";
?>
For php5:
php --version
PHP 5.5.38-1-avature-ondrej-fork (cli) (built: Aug 31 2016 16:37:38)
php test.php
Closed with: true
For php7:
php --version
PHP 7.0.8-0ubuntu0.16.04.2 (cli) ( NTS )
php test.php
Closed with: false
2016-09-28 14:05:58
http://php5.kiev.ua/manual/ru/ziparchive.close.html
If you open archive without flags in PHP 5.6 then you can get errors on close:
Warning: ZipArchive::close(): Zip archive inconsistent in
And changes not saved.
You need use flag ZIPARCHIVE::OVERWRITE on $zip->open.
This issue happens for me only in php 5.6. In php 5.4 and before it works without any flags to $zip->open.
2017-01-08 20:22:23
http://php5.kiev.ua/manual/ru/ziparchive.close.html
I am not sure, but seems that $zip->close() can run into errors if the path specified in $zip->open is a relative path, not absolute.
So, when create archives, please specify ABSOLUTE PATH, not relative path for zip file to be created.
2021-12-16 16:22:21
http://php5.kiev.ua/manual/ru/ziparchive.close.html