Here's a little extension to ZipArchive that handles directories recursively:
<?php
class Zipper extends ZipArchive {
public function addDir($path) {
print 'adding ' . $path . '<br>';
$this->addEmptyDir($path);
$nodes = glob($path . '/*');
foreach ($nodes as $node) {
print $node . '<br>';
if (is_dir($node)) {
$this->addDir($node);
} else if (is_file($node)) {
$this->addFile($node);
}
}
}
} // class Zipper
?>
ZipArchive::addFile
(PHP 5 >= 5.2.0, PECL zip >= 1.1.0)
ZipArchive::addFile — 指定したパスからファイルを ZIP アーカイブに追加する
説明
bool ZipArchive::addFile
( string $filename
[, string $localname
] )
指定したパスから、ファイルを ZIP アーカイブに追加します。
パラメータ
- filename
-
追加するファイルへのパス。
- localname
-
ZIP アーカイブ内部での名前。
返り値
成功した場合に TRUE を、失敗した場合に FALSE を返します。
例
この例は、ZIP ファイルアーカイブ test.zip をオープンし、ファイル /path/to/index.txt を newname.txt という名前で追加します。
例1 オープンおよび抽出
<?php
$zip = new ZipArchive;
if ($zip->open('test.zip') === TRUE) {
$zip->addFile('/path/to/index.txt', 'newname.txt');
$zip->close();
echo '成功';
} else {
echo '失敗';
}
?>
ZipArchive::addFile
peter at boring dot ch
22-Aug-2009 01:10
22-Aug-2009 01:10
christophe dot braud at aquafadas dot com
11-Aug-2009 10:10
11-Aug-2009 10:10
If you have some warnings with ZipArchiveImproved since the last Ubuntu update, replace "self::CREATE" by "self::CREATE | self::OVERWRITE" in the reopen function
christophe
garcia at no_span dot krautzer-lynn dot com
24-Mar-2009 02:31
24-Mar-2009 02:31
If you add files that have an absolut path, like for example:
/mnt/repository/my_file.pdf
the standard windows zip utility will not be able to extract the files. The first slash trips the zip utility. You have to add relative file paths or use a symbolic link.
ss at littlerain dot com
31-Jan-2009 12:45
31-Jan-2009 12:45
Note that the file isn't actually added to the archive until the $zip->close() method is called. I spent a lot of time trying to figure out why no time() went by after adding large files via $zip->addFile() but would then time out the script.
Farzad Ghanei
18-Jan-2009 10:53
18-Jan-2009 10:53
here is a basic class that extends the ZipArchive to:
* add a functionality to report the ZIP file address (I needed it and I could not find out how in ZipArchive documentation).
* resolve the problem of adding so many files to the archive due file descriptor limit. the ZipArchiveImproved::addFile() handles this.
<?php
/**
* ZipArchiveImproved extends ZipArchive to add some information about the zip file and some functionality.
*
*
*
* @author Farzad Ghanei
* @uses ZipArchive
* @version 1.0.0 2009-01-18
*/
class ZipArchiveImproved extends ZipArchive {
protected $_archiveFileName = null;
protected $_newAddedFilesCounter = 0;
protected $_newAddedFilesSize = 100;
/**
* returns the name of the archive file.
*
* @return string
*/
public function getArchiveFileName() {
return $this->_archiveFileName;
}
/**
* returns the number of files that are going to be added to ZIP
* without reopenning the stream to file.
*
* @return int
*/
public function getNewAddedFilesSize() {
return $this->_newAddedFilesSize;
}
/**
* sets the number of files that are going to be added to ZIP
* without reopenning the stream to file. if no size is specified, default is 100.
*
* @param int
* @return ZipArchiveImproved self reference
*/
public function setNewlAddedFilesSize($size=100) {
if ( empty($size) || !is_int($size) || $size < 1) {
$size = 100;
}
$this->_newAddedFilesSize = $size;
return $this;
}
/**
* opens a stream to a ZIP archive file. calls the ZipArchive::open() internally.
* overwrites ZipArchive::open() to add the archiveFileName functionality.
*
* @param string $fileName
* @param int $flags
* return mixed
*/
public function open($fileName, $flags) {
$this->_archiveFileName = $fileName;
$this->_newAddedFilesCounter = 0;
return parent::open($fileName,$flags);
}
/**
* closes the stream to ZIP archive file. calls the ZipArchive::close() internally.
* overwrites ZipArchive::close() to add the archiveFileName functionality.
*
* @return bool
*/
public function close() {
$this->_archiveFileName = null;
$this->_newAddedFilesCounter = 0;
return parent::close();
}
/**
* closes the connection to ZIP file and openes the connection again.
*
* @return bool
*/
public function reopen() {
$archiveFileName = $this->_archiveFileName;
if ( !$this->close() ) {
return false;
}
return $this->open($archiveFileName,self::CREATE);
}
/**
* adds a file to a ZIP archive from the given path. calls the ZipArchive::addFile() internally.
* overwrites ZipArchive::addFile() to handle maximum file connections in operating systems.
*
* @param string $fileName the path to file to be added to archive
* @param string [optional] $localname the name of the file in the ZIP archive
* @return bool
*/
public function addFile( $fileName ) {
if ($this->_newAddedFilesCounter >= $this->_newAddedFilesSize) {
$this->reopen();
}
if ( func_num_args() > 1 ) {
$flags = func_get_arg(1);
$added = parent::addFile($fileName,$flags);
if ($added) {
$this->_newAddedFilesCounter++;
}
return $added;
}
$added = parent::addFile($fileName);
if ($added) {
$this->_newAddedFilesCounter++;
}
return $added;
} // public function addFile()
}
?>
marco at maranao dot ca
15-Dec-2008 06:45
15-Dec-2008 06:45
This is my workaround for the file descriptor limit by closing/opening the archive file periodically.
<?php
if($backup = new ZipArchive()) {
if($backup->open($zip, ZIPARCHIVE::OVERWRITE) === true) {
$backup->addFile($file['realpath'], $file['path']);
if(($count++) == 200) { // the file descriptor limit
$backup->close();
if($backup = new ZipArchive()) {
$backup->open($zip);
$count = 0;
}
}
}
$backup->close();
}
?>
Hope it helps someone.
javierseixas at gmail dt com
17-Jul-2008 03:30
17-Jul-2008 03:30
I have had several problems trying adding files, because of a path problem. The error gived was this:
ZipArchive::addFile() [function.ZipArchive-addFile]: Unable to access <path>
I used an absolute root starting by "/", and it didn't work. Try starting your path with "./" (referencing the root of your site).
wacher at freemail dot hu
23-Jun-2008 08:03
23-Jun-2008 08:03
The workaround above (file_get_contents) is very dangerous if you pack large files. (see memory limit).
Close/open the zip archive periodically instead of using file_get_contents().
stanleyshilov {} gmail.com
11-May-2008 07:05
11-May-2008 07:05
It should be noted that the example provided above is not accurate.
Unlike extractTo, zip_open does not return a boolean result, so the above example will always fail.
mike at thetroubleshooters dot dk
07-Feb-2008 03:20
07-Feb-2008 03:20
What is worse is that when you run out of filedescriptors it seems to fail silently, I have not been able to find any errors in any logfiles.
Andreas R. newsgroups2005 at geekmail de
04-Apr-2007 01:29
04-Apr-2007 01:29
Currently the number of files that can be added using addFile to the ZIP archive (until it is closed) is limited by file descriptors limit. This is an easy workaround (on the bug links below you can find another workarounds):
<?php
/** work around file descriptor number limitation (to avoid failure
* upon adding more than typically 253 or 1024 files to ZIP) */
function addFileToZip( $zip, $path, $zipEntryName ) {
// this would fail with status ZIPARCHIVE::ER_OPEN
// after certain number of files is added since
// ZipArchive internally stores the file descriptors of all the
// added files and only on close writes the contents to the ZIP file
// see: http://bugs.php.net/bug.php?id=40494
// and: http://pecl.php.net/bugs/bug.php?id=9443
// return $zip->addFile( $path, $zipEntryName );
$contents = file_get_contents( $path );
if ( $contents === false ) {
return false;
}
return $zip->addFromString( $zipEntryName, $contents );
}
?>
