PHPのお勉強!

PHP TOP

ZipArchive::addFile

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

ZipArchive::addFile指定したパスからファイルを ZIP アーカイブに追加する

説明

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

指定したパスから、ファイルを ZIP アーカイブに追加します。

注意: ポータビリティを考慮して、ZIP ファイル名のディレクトリ区切り文字には常にスラッシュ (/) を使うことを推奨します。

パラメータ

filepath

追加するファイルへのパス。

entryname

空でない値を指定した場合は ZIP アーカイブ内部での名前となり、filepath を上書きします。

start

ファイルを一部コピーする場合の開始位置。

length

ファイルを一部コピーする場合の、コピーする長さ。 ZipArchive::LENGTH_TO_END (0) を指定すると、 ファイルサイズのぶんだけコピーします。 ZipArchive::LENGTH_UNCHECKED を指定すると、 start の位置から)ファイル全体をコピーします。

flags

以下のビットマスクの組み合わせ: ZipArchive::FL_OVERWRITE, ZipArchive::FL_ENC_GUESS, ZipArchive::FL_ENC_UTF_8, ZipArchive::FL_ENC_CP437, ZipArchive::FL_OPEN_FILE_NOW。 これらの定数の振る舞いは、定義済みの定数 で説明しています。

戻り値

成功した場合に true を、失敗した場合に false を返します。

変更履歴

バージョン 説明
8.0.0, PECL zip 1.18.0 flags が追加されました。
8.3.0, PECL zip 1.22.1 ZipArchive::FL_OPEN_FILE_NOW が追加されました。
8.3.0, PECL zip 1.22.2 ZipArchive::LENGTH_TO_ENDZipArchive::LENGTH_UNCHECKED が追加されました。

この例は、ZIP ファイルアーカイブ test.zip をオープンし、ファイル /path/to/index.txtnewname.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
'失敗';
}
?>

注意

注意:

アーカイブにファイルを追加するよう設定すると、PHP はそのファイルをロックします。 ロックが解除されるのは、ZipArchive::close() を呼ぶなり ZipArchive オブジェクトを破棄するなりして ZipArchive オブジェクトが閉じられたときだけです。 そのため、追加しようとしているファイルがロックが解除される前に削除されるようなことは起こりません。

参考

add a note

User Contributed Notes 34 notes

up
64
jayarjo
14 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
33
john factorial
13 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
20
aartdebruijn at gmail dot com
14 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
10
frame86 at live dot com
10 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
7
romuloum at hotmail dot com
10 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
2
610010559 at qq dot com
2 years 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
2
stanislav dot eckert at vizson dot de
9 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
6
camuc at camuc dot net
14 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
6
wacher at freemail dot hu
16 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
6
garcia at no_span dot krautzer-lynn dot com
15 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
1
gio AT giombg dot com
6 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
4
Anonymous
14 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
1
sp at read dot eu
12 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
1
kris at blacksuitmedia [do/t/] c0m
11 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
2
peter at boring dot ch
15 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

?>