Работа с ZIP архивами в PHP
Расширение архива Zip в PHP используется для работы с Zip архивами и файлами, которые в них содержатся. Для использования этого расширения в PHP 5 необходимо активировать php_zip.dll внутри файла php.ini. В этой статье вы узнаете о том, как работать с файлами Zip архивов в PHP, используя ряд PHP демо-приложений. Вы научитесь: создавать Zip архивы;
- создавать Zip архивы;
- добавлять файлы и папки в архив из строки и данной дорожки;
- удалять и переименовывать файлы, используя их индексы и имена;
- составлять список характеристик объектов ZipArchive (количество файлов, имя файла, комментарии, statusSys и т. д.).
Создание Zip архивов в PHP и добавление файлов
Для создания Zip архива в PHP можно использовать предопределенную константу ZIPARCHIVE::CREATE; архив будет создан, если он еще не существует. (Для добавления файлов внутрь архива можно использовать вышеописанные методы addFile и addFromString.) Первое демо-приложение (add_file_from_string.php) создает (если таковой еще не существует) или открывает Zip архив archive1.zip, а после добавляет в него файл, используя метод addFromString():
bool ZipArchive::addFromString ( string $localname , string $contents ): Добавить файл в Zip-архив, используя его содержание.
Здесь код для add_file_from_string.php:
С результаты выполнения add_file_from_string.php вы также можете ознакомиться на Рисунке 1.
Файловый текст test1.txt был успешно добавлен в archive1.zip
Второе демо-приложение (add_file_directory.php) также использует архив archive1.zip для печати всех характеристик объекта ZipArchive (статус, statusSys, numFiles, название файла, комментарии или специальные параметры, в нашем случае архивный комментарий и количество файлов), чтобы добавить пустой каталог под названием Subdirectory1. Это приложение также использует архив archive1.zip для добавления нового файла, используя метод addFile. Ниже содержатся прототипы методов addFile() и addEmptyDir():
bool ZipArchive::addFile ( string $filename [, string $localname ] ) : добавляет файл в Zip-архив с даного пути bool ZipArchive::addEmptyDir ( string $dirname ) : добавляет пустую папку в архив.
Здесь код для add_file_directory.php:
С результатом листинга add_file_directory.php вы также можете ознакомиться на Рисунке 2:
ZipArchive Object ( [status] => 0 [statusSys] => 0 [numFiles] => 2 [filename] => D:\Apache Group\Apache2\htdocs\php\ZIP\archive1.zip [comment] => PHP ZIP ARCHIVE ) Создан новый каталог Комментарий: PHP ZIP ARCHIVE № файла:4
Рисунок 2. Характеристики объекта archive2.zip
Следующее демо-приложение служит для создания Zip архива archive2.zip, который включает два файла: test3.txt и test4.txt. (Информацию о том, как пользоваться этим приложением, вы сможете найти ниже.) Код для archive2.php:
Результат archive2.php. Вы также можете ознакомиться с результатами на Рисунке 3: Файловый текст test3.txt успешно добавлен в archive2.zip при использовании метода addFile Файловый текст test4.txt успешно добавлен в archive2.zip при использовании метода addFromString method.
Рисунок 3. Содержание archive2.zip
Извлечение Zip архива в PHP
Демо-приложение этой части (extract_archives.php) показывает, как извлекать содержимое архива в специальную папку, используя метод extractTo():bool ZipArchive::extractTo ( string $destination [, mixed $entries ] ) : извлечь содержимое архива.
Архивы archive1.zip и archive2.zip будут извлечены в папку archive, как показано на Рисунке 4. Код для extract_archives.php:
Результат extract_archives.php: archive1.zip и archive2.zip были извлечены в папку archive!
Рисунок 4. Содержимое папки archive после извлечения archive1 и archive2
Следующее демо-приложение (extract_to_specified_folder.php) извлекает содержимое Zip архива в специальную папку, используя вышеописанный метод extractTo(). Код для extract_to_specified_folder.php:
Результат extract_to_specified_folder.php. Вы также можете ознакомиться с результатами на Рисунке 5: Архив извлечен в папку ZIP_extract!
Рисунок 5. Папка ZIP_extract с файлами archive1
С результатами листинга filelist.php вы также можете ознакомиться с на Рисунке 6: Файлы test3.txt и test4.txt из архива archive2.zip успешно извлечены в указанный каталог ZIP_TEST!
Рисунок 6.Выбранные файлы, извлеченные из archive2 в назначеный каталог ZIP_TEST
Получение характеристик объекта на основе его индекса
Для получения характеристик отдельного файла можно использовать метод statIndex:
mixed ZipArchive::statIndex ( int $index [, int $flags ] ).
Следующее демо-приложение (statIndex.php) итерирует список файлов в archive2.zip и печатает характеристики для каждого из объектов. Код для statIndex.php:
Array ( [name] => test3.txt [index] => 0 [crc] => -1117485446 [size] => 45
[mtime] => 1269720238
[comp_size] => 46 [comp_method] => 8 )
Array ( [name] => test4.txt [index] => 1 [crc] => -1780851877 [size] => 77 [mtime] => 1269786772 [comp_size] => 62 [comp_method] => 8 )
Следующее демо-приложение (locate.php) также позволяет получать характеристики файла, при условии что archive1.zip содержит этот файл. Метод locateName возвращает индекс файла в архиве и использует предопределенную константу ZIPARCHIVE::FL_NODIR, которая игнорирует компонент каталог. Прототип константы ZIPARCHIVE::FL_NODIR :
mixed ZipArchive::locateName ( string $name [, int $flags ] )
Array ( [name] => test2.txt [index] => 2 [crc] => -513033757 [size] => 50 [mtime] => 1269715222 [comp_size] => 49 [comp_method] => 8 )
Удаление и переименование Zip архивов в PHP
Для удаления или переименования Zip архивов в PHP можно использовать имя или индекс. Методы, которыми можно воспользоваться для этой цели, включают:
bool ZipArchive::deleteIndex ( int $index ) – Удаляет объект в архиве, используя индекс; bool ZipArchive::deleteName ( string $name ) – Удаляет объект в архиве, используя имя; bool ZipArchive::renameIndex ( int $index , string $newname ) – Переименует объект на основе индекса; bool ZipArchive::renameName ( string $name , string $newname ) – Переименует объект на основе имени.
Следующее демо-приложение (rename.php) использует все вышеперечисленные методы для переименования файла с «index=3», как «renameByIndex.txt», и «test4.txt», как «renameByName.txt». Код для rename.php:
Результаты листинга rename.php. Вы также можете ознакомиться с результатами на Рисунке 7 и Рисунке 8: Файлы успешно переименованы в архиве archive2.zip!
Рисунок 7. Исходное содержимое archive2.zip
Рисунок 8. Содержание архива archive2.zip после того, как файлы были переименованы
Следующее приложение (delete.php) удаляет из archive2.zip файл с «index=1» и текстовый файл renameByIndex.txt, используя методы deleteIndex() и deleteName(). Код для delete.php:
В связи с тем, что архив содержал всего два файла и оба были удалены, archive2.zip был также удален. Следующее приложение (add_text_files.php) итерирует архивные файлы и добавляет все файлы .txt из настоящего каталога в text_archive.zip. Код для add_text_files.php:
Результаты листинга add_text_files.php: text_archive.zip успешно создан!
Рисунок 9. Группировка всех текстовых файлов из текущего каталога в новый архив text_archive.zip
Заключение
Как вы, наверное, заметили, изучая приложения, представленные в статье, работать с расширением архива Zip в PHP довольно просто и даже забавно. Все, что от вас требуется, это умение обращаться с методами расширения. В этом случае вы с успехом сможете осуществлять различные операции с Zip архивами.
Примеры
$zip -> addFromString ( «testfilephp.txt» . time (), «#1 Это тестовая строка добавляется в качестве testfilephp.txt.\n» );
$zip -> addFromString ( «testfilephp2.txt» . time (), «#2 Это тестовая строка добавляется в качестве testfilephp2.txt.\n» );
$zip -> addFile ( $thisdir . «/too.php» , «/testfromfile.php» );
echo «numfiles: » . $zip -> numFiles . «\n» ;
echo «status:» . $zip -> status . «\n» ;
$zip -> close ();
?>
Пример #2 Собрать и отобразить подробную информацию об архиве
$za -> open ( ‘test_with_comment.zip’ );
print_r ( $za );
var_dump ( $za );
echo «numFiles: » . $za -> numFiles . «\n» ;
echo «status: » . $za -> status . «\n» ;
echo «statusSys: » . $za -> statusSys . «\n» ;
echo «filename: » . $za -> filename . «\n» ;
echo «comment: » . $za -> comment . «\n» ;
for ( $i = 0 ; $i < $za ->numFiles ; $i ++) echo «index: $i \n» ;
print_r ( $za -> statIndex ( $i ));
>
echo «numFile:» . $za -> numFiles . «\n» ;
?>
Пример #3 Использование обёртки потока Zip, чтение метаинформации OpenOffice
$reader -> open ( ‘zip://’ . dirname ( __FILE__ ) . ‘/test.odt#meta.xml’ );
$odt_meta = array();
while ( $reader -> read ()) if ( $reader -> nodeType == XMLREADER :: ELEMENT ) $elm = $reader -> name ;
> else if ( $reader -> nodeType == XMLREADER :: END_ELEMENT && $reader -> name == ‘office:meta’ ) break;
>
if (! trim ( $reader -> value )) continue;
>
$odt_meta [ $elm ] = $reader -> value ;
>
>
print_r ( $odt_meta );
?>
Этот пример использует старую версию API (PHP 4), он открывает ZIP-архив, читает каждый файл в архиве и выводит его содержимое. Архив test2.zip , использованный в этом примере, является одним из тестовых архивов исходного дистрибутива ZZIPlib.
Пример #4 Пример использования Zip
$zip = zip_open ( «/tmp/test2.zip» );
if ( $zip ) while ( $zip_entry = zip_read ( $zip )) echo «Название: » . zip_entry_name ( $zip_entry ) . «\n» ;
echo «Исходный размер: » . zip_entry_filesize ( $zip_entry ) . «\n» ;
echo «Сжатый размер: » . zip_entry_compressedsize ( $zip_entry ) . «\n» ;
echo «Метод сжатия: » . zip_entry_compressionmethod ( $zip_entry ) . «\n» ;
if ( zip_entry_open ( $zip , $zip_entry , «r» )) echo «Содержимое файла:\n» ;
$buf = zip_entry_read ( $zip_entry , zip_entry_filesize ( $zip_entry ));
echo » $buf \n» ;
zip_entry_close ( $zip_entry );
>
echo «\n» ;
User Contributed Notes 5 notes
All these examples will not work if the php script has no write access within the folder.
Although you may say this is obvious, I found that in this case, $zip->open(«name», ZIPARCHIVE::CREATE) doesn’t return an error as it might not try to access the file system but rather allocates memory.
It is only $zip->close() that returns the error. This might cause you seeking at the wrong end.
you can use this code for reading JAR files (java archives)
JAR files use the same ZIP format, so can be easily read
$zf = zip_open(realpath(‘D:/lucene/allinone/lucene-core.jar’)); $i=1;
while($zf && $ze = zip_read($zf)) $zi[$i][‘zip entry name’]= zip_entry_name($ze);
$zi[$i][‘zip entry filesize’]= zip_entry_filesize($ze);
$zi[$i][‘zip entry compressed size’]= zip_entry_compressedsize($ze);
$zi[$i][‘zip entry compression method’]= zip_entry_compressionmethod($ze);
$zi[$i][‘zip entry open status’] = zip_entry_open($zf,$ze);
//$zi[$i][‘zip entry file contents’] = zip_entry_read($ze,100);
$i++;
>
print_r($zi);
zip_close($zf);
$zip = new ZipArchive ;
$zip -> open ( ‘teste.zip’ );
$zip -> extractTo ( ‘./’ );
$zip -> close ();
echo «Ok!» ;
?>?php>
1) If you want to add files to a ZIP archive but you don’t know if the ZiP file exists or not, you MUST check: this changes the way you open it !.
2) you can not append multiple flags, can use only one (or none).
If the zip does not exists, open it with:
$ziph->open($archiveFile, ZIPARCHIVE::CM_PKWARE_IMPLODE)
(or a different compression method)
If the zip already exists, open it with:
$ziph->open($archiveFile)
or
$ziph->open($archiveFile, ZIPARCHIVE::CHECKCONS)
Example: make backup files every hour and ZIP them all in a daily ZIP archive, so you want to get only one ZIP per day, each ZIP containing 24 files:
function archivebackup ( $archiveFile , $file , & $errMsg )
$ziph = new ZipArchive ();
if( file_exists ( $archiveFile ))
if( $ziph -> open ( $archiveFile , ZIPARCHIVE :: CHECKCONS ) !== TRUE )
$errMsg = «Unable to Open $archiveFile » ;
return 1 ;
>
>
else
if( $ziph -> open ( $archiveFile , ZIPARCHIVE :: CM_PKWARE_IMPLODE ) !== TRUE )
$errMsg = «Could not Create $archiveFile » ;
return 1 ;
>
>
if(! $ziph -> addFile ( $file ))
$errMsg = «error archiving $file in $archiveFile » ;
return 2 ;
>
$ziph -> close ();
If you find your zip file not being created make sure every file you are adding to the zip is valid. If even one file is not available when zip->close is called then the archive will fail and your zip file won’t be created.