文字

ZipArchive::addFile

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

ZipArchive::addFileAdds a file to a ZIP archive from the given path

说明

bool ZipArchive::addFile ( string $filename [, string $localname = NULL [, int $start = 0 [, int $length = 0 ]]] )

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

参数

filename

The path to the file to add.

localname

If supplied, this is the local name inside the ZIP archive that will override the filename.

start

This parameter is not used but is required to extend ZipArchive.

length

This parameter is not used but is required to extend ZipArchive.

返回值

成功时返回 TRUE , 或者在失败时返回 FALSE

范例

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

Example #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' ;
}
?>

注释

Note:

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.

用户评论:

[#1] stanislav dot eckert at vizson dot de [2015-03-02 11:43:09]

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.

[#2] todd at toddwiggins dot com dot au [2014-05-15 03:31:50]

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.

[#3] frame86 at live dot com [2014-04-13 04:48:11]

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.

[#4] romuloum at hotmail dot com [2014-04-03 19:00:35]

If you have problem with windows explorer reading zipfile created by linux, try:
$oZip->addFile ( $file_name, " " . basename ( $file_name ) )
That space " " should solve.

[#5] s dot eckert dot spam at gmx dot com [2013-10-11 15:27:53]

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");

[#6] arrtedone at gmail dot com [2013-08-29 08:19:46]

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)

[#7] kris at blacksuitmedia [do/t/] c0m [2013-04-25 20:41:40]

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($fileZipArchive::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.

[#8] Dean Rather [2012-10-31 03:47:50]

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 '

class ZipArchiveImproved extends ZipArchive {
    protected 
$_archiveFileName null;
    protected 
$_newAddedFilesCounter 0;
    protected 
$_newAddedFilesSize 100;
    
    

    
public function getArchiveFileName() {
        return 
$this->_archiveFileName;
    }

    

    
public function getNewAddedFilesSize() {
        return 
$this->_newAddedFilesSize;
    }

    

    
public function setNewlAddedFilesSize($size=100) {
        if ( empty(
$size) || !is_int($size) || $size 1) {
            
$size 100;
        }
        
$this->_newAddedFilesSize $size;
        return 
$this;
    }

    

    
public function open($fileName$flags) {
        
$this->_archiveFileName $fileName;
        
$this->_newAddedFilesCounter 0;
        return 
parent::open($fileName,$flags);
    }

    

    
public function close() {
        
$this->_archiveFileName null;
        
$this->_newAddedFilesCounter 0;
        return 
parent::close();
    }

    

    
public function reopen() {
        
$archiveFileName $this->_archiveFileName;
        if ( !
$this->close() ) {
            return 
false;
        }
        return 
$this->open($archiveFileName,self::CREATE);
    }

    

    
public function addFile$fileName ) {
        if (
$this->_newAddedFilesCounter >= $this->_newAddedFilesSize) {
            
$this->reopen();
        }
        if ( 
func_num_args() > ) {
            
$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()
}
?>

[#23] marco at maranao dot ca [2008-12-15 10:45:46]

This is my workaround for the file descriptor limit by closing/opening the archive file periodically.

<?php
if($backup = new ZipArchive()) {
    if(
$backup->open($zipZIPARCHIVE::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.

[#24] javierseixas at gmail dt com [2008-07-17 08:30:42]

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).

[#25] wacher at freemail dot hu [2008-06-23 13:03:10]

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().

[#26] stanleyshilov {} gmail.com [2008-05-11 12:05:35]

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.

[#27] mike at thetroubleshooters dot dk [2008-02-07 07:20:24]

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.

[#28] Andreas R. newsgroups2005 at geekmail de [2007-04-03 18:29:23]

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
    

    
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 );
    }
?>

上一篇: 下一篇: