文字

ZipArchive 类

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

简介

一个用 Zip 压缩的文件存档。

类摘要

ZipArchive {
bool addEmptyDir ( string $dirname )
bool addFile ( string $filename [, string $localname = NULL [, int $start = 0 [, int $length = 0 ]]] )
bool addFromString ( string $localname , string $contents )
bool addGlob ( string $pattern [, int $flags = 0 [, array $options = array() ]] )
bool addPattern ( string $pattern [, string $path = "." [, array $options = array() ]] )
bool close ( void )
bool deleteIndex ( int $index )
bool deleteName ( string $name )
bool extractTo ( string $destination [, mixed $entries ] )
string getArchiveComment ([ int $flags ] )
string getCommentIndex ( int $index [, int $flags ] )
string getCommentName ( string $name [, int $flags ] )
bool GetExternalAttributesIndex ( int $index , int &$opsys , int &$attr [, int $flags ] )
bool getExternalAttributesName ( string $name , int &$opsys , int &$attr [, int $flags ] )
string getFromIndex ( int $index [, int $length = 0 [, int $flags ]] )
string getFromName ( string $name [, int $length = 0 [, int $flags ]] )
string getNameIndex ( int $index [, int $flags ] )
string getStatusString ( void )
resource getStream ( string $name )
int locateName ( string $name [, int $flags ] )
mixed open ( string $filename [, int $flags ] )
bool renameIndex ( int $index , string $newname )
bool renameName ( string $name , string $newname )
bool setArchiveComment ( string $comment )
bool setCommentIndex ( int $index , string $comment )
bool setCommentName ( string $name , string $comment )
bool setCompressionIndex ( int $index , int $comp_method [, int $comp_flags = 0 ] )
bool setCompressionName ( string $name , int $comp_method [, int $comp_flags = 0 ] )
bool setExternalAttributesIndex ( int $index , int $opsys , int $attr [, int $flags ] )
bool setExternalAttributesName ( string $name , int $opsys , int $attr [, int $flags ] )
public bool setPassword ( string $password )
array statIndex ( int $index [, int $flags ] )
array statName ( string $name [, int $flags ] )
bool unchangeAll ( void )
bool unchangeArchive ( void )
bool unchangeIndex ( int $index )
bool unchangeName ( string $name )
}

属性

status

Zip Archive 的状态

statusSys

Zip Archive 的系统状态

numFiles

压缩包里的文件数

filename

在文件系统里的文件名

comment

压缩包的注释

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::close — Close the active archive (opened or newly created)
  • 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::locateName — Returns the index of the entry in the archive
  • ZipArchive::open — Open a ZIP file archive
  • ZipArchive::renameIndex — Renames an entry defined by its index
  • ZipArchive::renameName — Renames an entry defined by its name
  • 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::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 — 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.

用户评论:

[#1] ohcc at 163 dot com [2015-11-28 18:14:56]

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

Examples

Warning: Unknown: Cannot destroy the zip context in Unknown on line 0

<?php         
    $za 
= 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

<?php         
    $za 
= 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.

<?php         
    $za 
= new ZipArchive;
    
$za->open('51-n.com.zip',ZipArchive::CREATE|ZipArchive::OVERWRITE);
    
$za->addFromString('wuxiancheng.cn.txt','yes');
    
$za->close();
?>

[#2] ohcc at 163 dot com [2015-11-06 20:58:43]

<?php
    
//use bzip2 + ZipArchive to reduce file size of your zip archives.
    
$zip = new ZipArchive;
    
$zip->open('i.zip',ZIPARCHIVE::CREATE|ZIPARCHIVE::OVERWRITE);
    
$file='wuxiancheng.cn.sql';
    
$bzFilename $file.'.bz2';
    
$sql file_get_contents($file);
    
$sql bzcompress($sql,9);
    
$zip->addFromString($bzFilename,$sql);
    
$zip->setArchiveComment('zipped on '.date('Y-M-d'));
?>

[#3] nick at fullfatthings dot com [2015-03-24 14:59:24]

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.

[#4] ebestwebmaster at gmail dot com [2014-12-16 11:46:16]

A way of zipping files and downloading them thereafter:
<?php

 $files 
= array('image.jpeg','text.txt','music.wav');
$zipname 'enter_any_name_for_the_zipped_file.zip';
$zip = new ZipArchive;
$zip->open($zipnameZipArchive::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);

?>

[#5] piotr dot stop dot spam at gmail dot com [2014-01-17 16:58:27]

You can check general purpose flag to test if the zip file is encrypted. Example function below.

<?php


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

[#6] AshleyDambra at live dot com [2013-05-16 08:23:26]

Simple class xZip to zip big folders into multiple parts and unzip multi zip files at once.

<?php
class xZip {
    public function 
__construct() {}
    private function 
_rglobRead($source, &$array = array()) {
        if (!
$source || trim($source) == "") {
            
$source ".";
        }
        foreach ((array) 
glob($source "
  
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);
  }

  

  
public static function zipDir($sourcePath$outZipPath)
  {
    
$pathInfo pathInfo($sourcePath);
    
$parentPath $pathInfo['dirname'];
    
$dirName $pathInfo['basename'];

    
$z = new ZipArchive();
    
$z->open($outZipPathZIPARCHIVE::CREATE);
    
$z->addEmptyDir($dirName);
    
self::folderToZip($sourcePath$zstrlen("$parentPath/"));
    
$z->close();
  }
}
?>

[#8] niklas dot schumi at NOSPAM dot googlemail dot com [2012-08-02 10:44:42]

Hi there.
I just wrote a little function to zip a whole folder while maintaining the dir-structure. I hope it might help someone.

<?php
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:
<?php
$z 
= new ZipArchive();
$z->open("test.zip"ZIPARCHIVE::CREATE);
folderToZip("storeThisFolder"$z);
$z->close();
?>


Have a good day!

[#9] panique at web dot de [2012-07-14 11:21:48]

Important: Due to the natural file size limit of 4GB (~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.

[#10] bruno dot vibert at bonobox dot fr [2012-05-09 20:21:32]

There is a usefull function to get the ZipArchive status as a human readable string :

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

?>

[#11] webmaster at sebastiangrinke dot info [2011-10-06 13:30:25]

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

<?php
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{return 
$archiv;}
        if(
$mode=='unzip'){$archiv->extractTo($data);}
    }
?>

[#12] Jerry dot Saravia at emc dot com [2011-08-08 13:57:06]

The following code can be used to get a list of all the file names in a zip file.

<?php
$za 
= new ZipArchive();

$za->open('theZip.zip');

for( 
$i 0$i $za->numFiles$i++ ){
    
$stat $za->statIndex$i );
    
print_rbasename$stat['name'] ) . PHP_EOL );
}
?>

[#13] h-fate at gmx dot net [2010-10-05 04:17:12]

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.

[#14] hardcorevenom at gmx dot com [2010-06-15 15:17:07]

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.

<?php
$zip 
= 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($fp2048); //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.

上一篇: 下一篇: