谷歌镜像 伍佰目录 短网址
  当前位置:海洋目录网 » 站长资讯 » 站长资讯 » 文章详细 订阅RssFeed

PHP - Manual: ZipArchive::addFile

来源:网络转载 浏览:35439次 时间:2023-11-20
ZipArchive::addFromString » « ZipArchive::addEmptyDir
  • PHP 手册
  • 函数参考
  • 压缩与归档扩展
  • Zip
  • ZipArchive

ZipArchive::addFile

(PHP 5 >= 5.2.0, PHP 7, PHP 8, PECL zip >= 1.1.0)

ZipArchive::addFile — Adds a file to a ZIP archive from the given path

说明

public ZipArchive::addFile(
    string $filepath,
    string $entryname = "",
    int $start = 0,
    int $length = 0,
    int $flags = ZipArchive::FL_OVERWRITE
): bool

Adds a file to a ZIP archive from a given path.

注意: 为了最大限度地提高代码可移植性,建议在 ZIP 文件名中使用斜线 (/) 做为目录分隔符。

参数

filepath

The path to the file to add.

entryname

If supplied and not empty, this is the local name inside the ZIP archive that will override the filepath.

start

For partial copy, start position.

length

For partial copy, length to be copied, if 0 or -1 the whole file (starting from start) is used.

flags

Bitmask consisting of ZipArchive::FL_OVERWRITE, ZipArchive::FL_ENC_GUESS, ZipArchive::FL_ENC_UTF_8, ZipArchive::FL_ENC_CP437. The behaviour of these constants is described on the ZIP constants page.

返回值

成功时返回 true, 或者在失败时返回 false

更新日志

版本 说明
8.0.0 / 1.18.0 flags was added.

范例

This example opens a ZIP file archive test.zip and add the file /path/to/index.txt. as newname.txt.

示例 #1 Open and add

<?php
$zip = new ZipArchive;
if ($zip->open('test.zip') === TRUE) {
    $zip->addFile('/path/to/index.txt', 'newname.txt');
    $zip->close();
    echo 'ok';
} else {
    echo 'failed';
}
?>

注释

注意:

When a file is set to be added to the archive, PHP will lock the file. The lock is only released once the ZipArchive object has been closed, either via ZipArchive::close() or the ZipArchive object being destroyed. This may prevent you from being able to delete the file being added until after the lock has been released.

参见

  • ZipArchive::replaceFile() - Replace file in ZIP archive with a given path
add a note

User Contributed Notes 33 notes

up down 62 jayarjo12 years ago It is not obvious, since there are no noticeable examples around, but you can use $localname (second parameter) to define and control file/directory structure inside the zip. Use it if you do not want files to be included with their absolute directory tree.

<?php

$zip->addFile($abs_path, $relative_path);

?>
up down 6 frame86 at live dot com8 years ago The manual is lying.

"In short, it means you can first delete an added file after the archive is closed. "

Thats true but not by locking the file...
Warning! This method works asynchronous!

It seems that addFile() will return TRUE if the file stat command returns correctly, but the operation itself will not happen yet.

Instead, deleting a file is always possible. I have discovered this behaviour by using a temporary file and deleting it immediately after addFile() returns. The result was that no archive was created nor any file was added although every operation (creating,open(),addFile()) returned true before. The operation silenty fails.
up down 28 john factorial11 years ago Beware: calling $zip->addFile() on a file that doesn't exist will succeed and return TRUE, delaying the failure until you make the final $zip->close() call, which will return FALSE and potentially leave you scratching your head.

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.

It's also a good idea to check each file with file_exists() or is_readable() before calling $zip->addFile() on it.
up down 17 aartdebruijn at gmail dot com11 years ago When adding a file to your zip, the file is opened and stays open.
When adding over 1024 files (depending on your open files limit) the server stops adding files, resulting in a status 11 in your zip Archive. There is no warning when exceeding this open files limit with addFiles.

Check your open files with ulimit -a

This kept me busy for some time.
up down 5 romuloum at hotmail dot com8 years ago If you have problem with windows explorer reading zipfile created by linux, try:
$oZip->addFile ( $file_name, " " . basename ( $file_name ) )
That space " " should solve.
up down 5 wacher at freemail dot hu13 years ago 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().
up down 7 garcia at no_span dot krautzer-lynn dot com13 years ago 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.
up down 5 camuc at camuc dot net12 years ago In some versions of this library you NEED to add the "localfile" parameter or the file will not show in the Zip folder. up down 5 peter at boring dot ch12 years ago 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

?>
up down 2 kris at blacksuitmedia [do/t/] c0m9 years ago I had a huge number of files and folders that I needed to zip on a linux web server. I was running into timeout problems and file enumerator issues, as well as file handler limit issues (ulimit). I used a script to solve u limit offered by Farzad Ghanei first (ZipArchiveImproved), but closing and reopening his way didn't do the trick for me.

I eventually did a simple call to a $filelimit variable I created that records file handler limit I want my script to hit before it closes and reopens the file.
<?php
$filelimit = 255;

if ($zip->numFiles == $filelimit) {$zip->close(); $zip->open($file) or die ("Error: Could not reopen Zip");}
?>

This made some progress for me, timeouts were gone, but when calling
<?php $zip->addFile($filepath, $archivefilepath); ?>
after the reopening of the Zip, I got an error. I echoed the <?php $zip->numFiles; ?> and found that after reopening, the numFile enum reset to '0'.

A few more goose-chases later, I tried addFromString with some better results, but did not get it working 100% until I actually coupled addFromString with addFile! My working scripting for the add files function on massive file-folder structures looks like so:

<?php
$sourcefolder = /rel/path/to/source/folder/on/server/

$dirlist = new RecursiveDirectoryIterator($sourcefolder);

$filelist = new RecursiveIteratorIterator($dirlist);

//how many file can be added before a reopen is forced?
$filelimit = 245;

// Defines the action
$file = tempnam("tmp", "zip");
$zip = new ZipArchive();

// This creates and then gives the option to save the zip file

if ($zip->open($file, ZipArchive::OVERWRITE) !== TRUE) {

    die ("Could not open archive");

}

// adds files to the file list
foreach ($filelist as $key=>$value) {

    //fix archive paths
    $path = str_replace($sourcefolder, "", $key); //remove the source path from the $key to return only the file-folder structure from the root of the source folder
    if (!file_exists($key)) { die($key.' does not exist. Please contact your administrator or try again later.'); }
      if (!is_readable($key)) { die($key.' not readable. Please contact your administrator or try again later.'); }    
          if ($zip->numFiles == $filelimit) {$zip->close(); $zip->open($file) or die ("Error: Could not reopen Zip");}

    $zip->addFromString($path, $key) or die ("ERROR: Could not add file: $key </br> numFile:".$zip->numFiles);
    $zip->addFile(realpath($key), $path) or die ("ERROR: Could not add file: $key </br> numFile:".$zip->numFiles);
   
}

// closes the archive
$zip->close();

//make local temp file a .zip, rename, and move to output dir
rename ($file, "./" . $outputfolder . "/" . $zipfilename);
?>
I hope this may help someone else.
up down 2 ohcc at 163 dot com6 years ago Do NOT use ZipArchive::addFile() to append a folder.

When a folder's path is passed to ZipArchive::addFile(), the method returns true, but ZipArchive can neither create a zip archive nor can it make any change to a existing file.

<?php
    $z = new ZipArchive();
    if(true === ($z->open('./foo.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE))){
        $z->setArchiveComment('Interesting!');
        $z->addFromString('domain.txt', 'wuxiancheng.cn');
        $folder = './test';
        !is_dir($folder) && mkdir($folder); // Create an folder for testing
        if(true === $z->addFile($folder)){
            echo 'success'; // !!!
        }
        rmdir($folder);
        $z->close();
        // foo.zip will NOT be saved on disk.
        // If foo.zip already exists before we run this script, the file will remain unchanged.
    }
?>
up down 4 Anonymous12 years ago On my system (Windows), I found that ZipArchive uses IBM850 encoding for filenames (localname). For filenames with special characters such as (é) &eacute; which appears at 0xE9 in the ISO-8859-1, it is at 0x82 in IBM850. I had to call iconv('ISO-8859-1', 'IBM850', 'Québec') to get correct file names. up down 1 sp at read dot eu10 years ago Note that using addFile() will change the order of the files within the zip, in fact within the index of the zip. Does not matter much, except if you loop the index and use addFile() within that loop : it will likely give messy results.

Example :
<?php
$zip = new ZipArchive;
if ($zip->open('somefile.zip') === TRUE) {
  for ($i = 0; $i < $zip->numFiles; $i++) {
    if (forsomereason()) {
      addFile('./somenewfile.ext', $zip->getNameIndex($i));
    }
  }
}
$zip->close();
?>

This code may loop for ever, depending on your forsomereason() function, or at least you're at risk.

Try something like this instead :

<?php
$zip = new ZipArchive;
if ($zip->open('somefile.zip') === TRUE) {
  for ($i = 0; $i < $zip->numFiles; $i++) {
    if (forsomereason()) {
      $couples[]=array('filename'=>'./somenewfile.ext','localname'=>$zip->getNameIndex($i));
    }
  }
}
foreach ($couples as $couple) $zip->addFile($couple['filename'],$couple['localname']);
$zip->close();
?>

Hope it helps ;-)
up down 0 610010559 at qq dot com3 months ago there are some points  can be more clear, it take me some time to figure out. hope it can help you.
1.use addFile() ,method to add the file with path to zip. if the directory not exist, addFile() would auto create it.
<?php
   ....
   //addFile would help you create the directory named not_exist_director before add the filename.txt file.
   $zip->addFile($fileToAdd, '/not_exist_directory/filename.txt');
   ...
?>

2. addFile() would overwrite the old file if exist in default.
<?php
   ....
   //if the filename.txt is exist in the zip, addFile() would overwrite it. because the the addFile fifth param is ZipArchive::FL_OVERWRITE by default.
   $zip->addFile($fileToAdd, '/filename.txt');
   ...
?>
up down 2 stanislav dot eckert at vizson dot de7 years ago 2 tips:

- The example in on this page is a bit misleading for new programmers. It works only if the ZIP archive file exists already. Don't forget to use ZipArchive::CREATE and optionally ZipArchive::OVERWRITE in the second optional parameter in the open() function.

- If you want to add files and directories recursively (see some examples from other comments here on this page) use scandir() instead of blob() because blob() does not list hidden files like ".htaccess" for example.
up down 0 raja at rsdisk dot com3 years ago zip->addfile function does not add file to archive immediately. It is cued and executed at zip->close()

I had backup files in a dir. with a foreach statement I was adding the file to an archive and then moving the files into dump dir immediately.

This caused an error.

<?php
$dir = getcwd().'/';
$dirContent = scandir('./');
foreach($dirContent as $file)
    if(strpos($file, '.sql')!==false)
{
    echo "adding $file ......";
    $zip->addFile($file);
        $newFileName = $dir."done/$file";
    rename($dir.$file, $newFileName);
    echo( "; file added\n");
}
$zip->close();
?>

The $zip->close() needs to execute before moving files,
<?php
foreach($dirContent as $file)
    if(strpos($file, '.sql')!==false)
{
    echo "adding $file ......";
    $zip->addFile($file);
    echo( "; file added\n");
}
$zip->close();
foreach($dirContent as $file)
    if(strpos($file, '.sql')!==false)
{
    $newFileName = $dir."done/$file";
    rename($dir.$file, $newFileName);
    echo( "$file moved\n");
}
?>
up down 0 gio AT giombg dot com4 years ago work 4 me

$zip = new ZipArchive;
$zip_name = ('name.zip');
$path_zip = ($config['path'].'/zip/'.$zip_name);
$zip->open($path_zip,ZipArchive::CREATE);
$zip->addFile($path1.'/'.$nam1,$nam1);
$zip->addFile($path2.'/'.$nam2,$nam2);
$zip->close();

ciao
GioMBG
up down 2 christophe dot braud at aquafadas dot com12 years ago 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
up down 2 Farzad Ghanei13 years ago 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()
}
?>
up down 0 todd at toddwiggins dot com dot au8 years ago The addFile() method does not accept the "file://" protocol. Strip away "file://" and use the absolute path instead.

I assume that it also does not accept any other protocols, I was having issues trying to add files, other functions within the application I was building required the use of the protocol.

Also to note, the status code returned did not match any of the predefined error codes, and the status code was never the same. My assumption was a overflow on the variable as the status codes were around the minimum and maximum INT values.
up down 0 s dot eckert dot spam at gmx dot com8 years ago Note that there is no concept of "folders" for ZIP files. If you need to store data into folders, use forward slashes ("/") in $localname to separate folder(s) and the file name.

Example:
$zip->addFile("test.txt", "mainfolder/subfolder/test.txt");
up down 0 Dean Rather9 years ago This add directory function does not require that you create a new wrapper class, and also does not add the entire file directory tree into your zip file.

<?php

public function addDirectoryToZip($zip, $dir, $base)
{
    $newFolder = str_replace($base, '', $dir);
    $zip->addEmptyDir($newFolder);
    foreach(glob($dir . '/*') as $file)
    {
        if(is_dir($file))
        {
            $zip = $this->addDirectoryToZip($zip, $file, $base);
        }
        else
        {
            $newFile = str_replace($base, '', $file);
            $zip->addFile($file, $newFile);
        }
    }
    return $zip;
}

?>
up down 0 shano10 years ago thought it might come in handy
recursively adds all directories and files within a directory

class zip extends ZipArchive {
   
    public function addDirectory($dir) { // adds directory
        foreach(glob($dir . '/*') as $file) {
            if(is_dir($file))
                $this->addDirectory($file);
            else
                $this->addFile($file);
        }
    }
}
up down 0 Andreas R. newsgroups2005 at geekmail de15 years ago 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 );
    }
?>
up down -1 ptipti at gala dot net10 years ago Another surprise, which took a lot of trouble. So that after you add a file to the archive it can be safely removed, took advantage of such construction:

if (!is_file ($archive)) :
    $result = $zip->open ($archive, ZipArchive::CREATE);
else :
    $result = $zip->open ($archive);
endif;
if ($result === TRUE) :
    if (($zip->addFile ($file, $filename)) === TRUE) :
        $theoreticaly_added = TRUE;
    endif;
    if ((($zip->close ()) === TRUE) && $theoreticaly_added) :
        unlink ($file);
    endif;
endif;

Now the files will not disappear. But perhaps there is a simpler solution, which gives 100% guarantee?
up down -1 javierseixas at gmail dt com13 years ago 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).
up down -2 ohcc at 163 dot com5 years ago 如果文件名包含汉字,ZIPARCHIVE::addFile() 会导致无法将文件压缩到压缩包中,或者压缩以后文件名乱码。

可以使用ZipArchive::addFromString()来实现。

注意:如果操作系统是Windows,文件系统编码是gbk.
如果php文件的文件编码是utf-8,需要相应转码。

ZipArchive::addFile() fails if the filename contains Chinese characters.

ZipArchive::addFromString() should be used instead.

<?php

    $z = new ZipArchive;

    $file = '吴先成.txt';

    if($z->open(ZIPARCHIVE::CREATE)===true){
        $z->addFromString($file, file_get_contents($file));
        //for windows
        //$z->addFromString($file, file_get_contents(iconv('utf-8', 'gbk//ignore', $file)));
    }
    // ...
up down -1 mike at thetroubleshooters dot dk14 years ago 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. up down -1 stanleyshilov {} gmail.com14 years ago 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.
up down -1 arrtedone at gmail dot com8 years ago Note that ZipArchive::open() not return boolean value, but integer, for example :
$zip = new ZipArchive();
$filename = '/tmp/test.zip';
var_dum($zip->open($filename)); // return's : int (11)
up down -1 ss at littlerain dot com13 years ago 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. up down -1 marco at maranao dot ca13 years ago 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.
up down -5 pelpet at ic dot cz12 years ago <?php
$zip=new ZipArchive;
$zip->addFile('path to the file', 'new name of the file');
?>

What I have to do, when I wan't to have the file in the zip archive with it's name before archiving?
(Sorry, I'm from Czech Republic and I can't speak English very well, if I did anywhere mistake, so ignore that pease :-)
add a note

官方地址:https://www.php.net/manual/en/ziparchive.addfile.php

  推荐站点

  • At-lib分类目录At-lib分类目录

    At-lib网站分类目录汇集全国所有高质量网站,是中国权威的中文网站分类目录,给站长提供免费网址目录提交收录和推荐最新最全的优秀网站大全是名站导航之家

    www.at-lib.cn
  • 中国链接目录中国链接目录

    中国链接目录简称链接目录,是收录优秀网站和淘宝网店的网站分类目录,为您提供优质的网址导航服务,也是网店进行收录推广,站长免费推广网站、加快百度收录、增加友情链接和网站外链的平台。

    www.cnlink.org
  • 35目录网35目录网

    35目录免费收录各类优秀网站,全力打造互动式网站目录,提供网站分类目录检索,关键字搜索功能。欢迎您向35目录推荐、提交优秀网站。

    www.35mulu.com
  • 就要爱网站目录就要爱网站目录

    就要爱网站目录,按主题和类别列出网站。所有提交的网站都经过人工审查,确保质量和无垃圾邮件的结果。

    www.912219.com
  • 伍佰目录伍佰目录

    伍佰网站目录免费收录各类优秀网站,全力打造互动式网站目录,提供网站分类目录检索,关键字搜索功能。欢迎您向伍佰目录推荐、提交优秀网站。

    www.wbwb.net