Создание zip архивов с помощью PHP скрипта
Думаю, никому не нужно объяснять, насколько широко сегодня используются zip архивы. Поддержка этого формата реализована во всех современных операционных системах, а библиотеки для работы с ним, написаны для большинства языков программирования.
В этой статье я покажу, как написать небольшой PHP скрипт, создающий zip архив.
Прежде всего, убедитесь, что включена поддержка всех нужных функций. Для этого в файле php.ini нужно убрать символ комментария (;) в начале строки:
extension=php_zip.dll
Теперь переходим к созданию архива.
Все операции с архивом выполняются с помощью объекта ZipArchive, создать его не сложно:
-
$zip = new ZipArchive();
После этого нужно создать файл архива с помощью метода open(), который в качестве параметров принимает имя архива и константу, указывающую способ открытия (об этом чуть позже).
Если на этом этапе ошибок не произошло, то с помощью метода addFile() можно добавить в архив файлы. Метод принимает два параметра:
первый – имя исходного файла;
второй – имя под которым файл будет добавлен в архив (если этот параметр не указан, будет использовано имя из первого параметра).
Примечание. Тут есть один нюанс. Если имя исходного файла “d:/docs/myfile.txt” и вы не укажите второй параметр, то в архиве будет создана папка “d”, а в ней – “docs”. Файл “myfile.txt” будет размещен в “docs”. Чтобы избежать создания папок в архиве просто укажите во втором параметре “myfile.txt”, и тогда файл будет размещен в корне архива.
Завершает работу с архивом метод close().
Так, с теорией закончили. Теперь посмотрим, как все это работает на примере.
Напишем небольшой скрипт, который будет создавать архив со всеми файлами из какой-нибудь папки.
-
<?php
-
//папка в которой будет размещен архив
-
$archive_dir = "E:/archiveFolder/";
-
//папка с исходными файлами
-
$src_dir = "E:/srcFolder/";
-
-
//создание zip архива
-
$zip = new ZipArchive();
-
//имя файла архива
-
$fileName = $archive_dir."backup_".date('j_m_Y_h_m_s').".zip";
-
if ($zip->open($fileName, ZIPARCHIVE::CREATE) !== true) {
-
fwrite(STDERR, "Error while creating archive file");
-
exit(1);
-
}
-
-
//добавляем файлы в архив все файлы из папки src_dir
-
$dirHandle = opendir($src_dir);
-
while (false !== ($file = readdir($dirHandle))) {
-
$zip->addFile($src_dir.$file, $file);
-
}
-
//закрываем архив
-
$zip->close();
-
-
fwrite(STDOUT, "Archive created\n");
-
-
exit(0);
-
?>
Переменная $src_dir содержит путь к папке с исходными файлами, а $archive_dir – путь к папке в которой будет создан архив.
Примечание: учтите, что наш скрипт эти папки не создает, поэтому сделайте это самостоятельно.
В переменной $fileName содержится имя архива. К имени я добавил дату и время создания архива в формате “день_месяц_год_часы_минуты_секунды”. Это позволяет многократно запускать скрипт и не думать о том, что новая версия архива запишется поверх старой.
В строках 11-14 мы открываем архив, при этом используется константа ZIPARCHIVE::CREATE, которая указывает, что если архива не существует, то он должен быть создан. Если во время создание архива возникли ошибки, выводим сообщение и завершаем работу.
После этого, мы открываем папку с исходными файлами и добавляем их в архив (строки 17-20).
Метод close() (в строке 22) закрывает архив.
Запускаем скрипт:
php путь_к_скрипту\имя_скрипта.php
Если ошибок не было, в папке "E:/archiveFolder/" вы будет создан архив.
Как видите, ничего сложного. В следующий раз я покажу как извлечь файлы из архива.
Постовой
Если нужен щебень заходите на vost.ru
Понравилась статья? Подписывайтесь на продолжение
!
Опубликовано в PHP Комментарии (68) »
Комментарии (68)
Вы можете отслеживать обсуждение записи с помощью RSS 2.0 ![]()
Вы также можете оставить комментарий, или трекбек с Вашего сайта.









А можно ли задать уровень компрессии (минимальный, максимальный…)?
Честно говоря, я не нашел в документации четкого ответа.
Но для создания архива PHP использует библиотеку zlib, для которой в php.ini можно задать два параметра:
zlib.output_compression
zlib.output_compression_level
Если есть желание, попробуйте поиграться.
А обязательно прописывать путь, по которому будет создан архив? Можно ли сделать так, чтобы пользователь сам выбрал, куда он хочет сохранить свой файл архива?
Можно, только это зависит от интерфейса с которым работает пользователь.
Если используется web интерфейс, то, один из вариантов, создать форму в которую он будет вводить путь к архиву. А после этого подставлять введенный путь.
а можно ли зазиповать целую папку с файлами?
Одной строкой кода – нет.
Но в этой статье я привел скрипт создания архива целой папки (последний листинг). Он в цикле проходит по всей папке и добавляет в архив все найденные файлы.
В общем-то его не сложно изменить для просмотра вложенных папок.
Сниппет для архивирования папки в zip-архив с помощью php. Надеюсь пригодится.
open('my-archive.zip', ZIPARCHIVE::CREATE) !== TRUE) {die ("Could not open archive");
}
// initialize an iterator
// pass it the directory to be processed
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator("app/"));
// iterate over the directory
// add each file found to the archive
foreach ($iterator as $key=>$value) {
$zip->addFile(realpath($key), $key) or die ("ERROR: Could not add file: $key");
}
// close and save archive
$zip->close();
echo "Archive created successfully.";
?>
Взято отсюда.
Небольшое дополнение. Ссылка на описание RecursiveIteratorIterator
"Fatal error: Cannot instantiate non-existent class: ziparchive in y:\home\localhost\www\foto\index.php on line 10"
хотя и в файле пхп.ини убрал значок комента….
в чем дело??может потомучто у меня стоит Денвер?
я уже даже скачал php_zip.dll и закинул в папку extensions…ошибка всё таже… почему не работает….??
Посмотрите, что выводит phpinfo(). Там должен быть раздел zip. И в нем параметры
Zip: enabled
Extension Version: $Id: php_zip.c,v 1.1.2.38 2007/08/06 22:02:32 bjori Exp $
Zip version: 2.0.0
Libzip version: 0.7.1
Версии могут отличаться.
там написано:
Zip support: enabled
и всё! как его подключать?
Подключать никак не надо. После того как библиотека загружена, $zip = new ZipArchive(); должен создать объект.
Вообще ситуация странная. Если хотите, отправьте мне скрипт по email, попробую запустить у себя.
пользуйтесь онлайн сервисом OnlineZIP.cn для создания архивов и отправки его на любой мейл
Внедрил скрипт, всё вроде хорошо работает, но если размер архива достигает 128кб, возвращаетса битый архив… счем может быть связана проблемма?
Возможная причина – ограничение времени выполнения скрипта или максимального объема памяти.
Настройки в php.ini:
memory_limit
max_execution_time
Спасибо, помогло
у меня тоже не создает объект
Class 'ZipArchive' not found in Z:\home\localhost\www\Mytest\music.sevstar.net\ZIP\zip.php on line 8
хотя в php.ini раскоментил extension=php_zip.dll
В php.info ZIPа нету …
А сервер перезапускали?
естественно
)
сейчас разместил не у себя, а на сервере другом. Эта проблешма ушла, но появилась следующая:
в строке fwrite(STDOUT, "Archive created\n")
пишет:
Warning: fwrite(): supplied argument is not a valid stream resource in …
хотя в коде у мну вот так:
$archive_dir = "archiveFolder/";
$src_dir = "1/";
в папке "1" пара фалов а "archiveFolder" не существует. ПРОбовл ставить и существующую, но та же проблема…
Попробуйте проверить существуют ли папки
is_dir($archive_dir)is_dir($src_dir)
если эти функции вернуть false, то папок не существует.
В этом случае попробуйте указать полный путь к папке.
Небольшая поправка.
Проверять нужно только $src_dir раз archiveFolder не существует.
А как происходит обратный процесс, когда требуется разархивировать файлы?
Используйте метод ZipArchive::extractTo (для разархивирования)
Например,
$zip = new ZipArchive;if ($zip->open('test.zip') === TRUE) {
$zip->extractTo('/my/destination/dir/');
$zip->close();
echo 'ok';
} else {
echo 'failed';
}
Подробная документация здесь.
Благодарю
Есть немного другой алгоритм :
Сори предыдущий можно удалить комент, не разобрался с тэгами
Есть другой алгоритм Создание Zip на php
Интересно, а производительность вы не сравнивали?
С файлами понятно, а если надо упаковать не файлы, а данные которые уже находятся в памяти?
Например данные могут динамически генерироваться или содержаться в скрипте в виде строк.
С файлами как понятно. А если надо упаковать не файлы а данные которые уже находятся в памяти? Например данные динамически генерируются на лету или находятся в скрипте в виде строк.
В zip архиве в любом случае должны быть файлы. Но вы можете использовать метод addFromString для того чтобы добавить в архив данные из памяти (при этом нужно будет указать имя файла который будет создан в архиве с этими данными).
Как сделать чтобы архив создавался в текущей папке? в котором были бы все файлы сайта. (я незнаю полный путь к этим файлам) Спасибо!
Если вы не знаете размещение файлов, то заархивировать их вы не сможете.
Если эти файлы находятся в той же папке, что и ваш скрипт, то узнать путь к нему можно с помощью $_SERVER['SCRIPT_FILENAME']
Здравствуйте!
Скопировал скрипт, вместо диска "е" указал "z", так как использую денвер. Пишет ошибку Warning: fwrite(): supplied argument is not a valid stream resource in Z:\home\arch.ru\www\1.php on line 24
zipZip enabled
Extension Version $Id: php_zip.c,v 1.1.2.49 2009/02/05 19:53:22 pajoye Exp $
Zip version 1.8.11
Libzip version 0.9.0
А при проверке на наличие директории (is_dir($src_dir)) пишеь 1.
Заранее спасибо.
Попробуйте изменить адрес на
Z:/home/arch.ru/www/1.php
Здравствуйте! Подскажите, как создать архив новостей на сайте? В смысле, чтобы новости не заменялись ежедневно, а было видно несколько страниц архивных новостей. Хостинг бесплатный. Заранее спасибо за ответ!
То, что хостинг бесплатный – это хорошо… но их много и они разные
У вас есть какая-нибудь панель управления или движок какой-то установлен?
Если вы можете выполнять свои php скрипты, то сделать однозначно можно. Если не можете, то все зависит от возможностей панели управления.
А можно ли усложнить пример?
с помощью пхп, зайти на фтп сервер взять от туда фаил, запаковать зипом и передать клиенту который его запрашивал.
пример реализовать возможно? зарание спс.
Да, усложнить можно, но что означает передать клиенту? Отправить почтой?
Или клиент заходит на сайт и выбирает файл из какого-нибудь списка?
А как можно создать запороленный архив при помощи php, можно ли его вообще создать при помощи php?
Это можно сделать с помощью с помощью внешних утилит, например, 7-zip. Этот архиватор допускает работу в режиме командной строки, т.е. его можно запустить с помощью функции exec
exec(""c:\\program files\\7-zip\\7z.exe" a archive.7z -psecret -mhe *.txt");
где secret – пароль
Путь к архиватору, естественно, нужно указать ваш.
Параметры командной строки описаны в справке.
" – это дополнительные кавычки, нужны, т.к. program files содержит пробел
Class 'ZipArchive' not found in
Ошибка даже после перезапуска Денвера. Что можно сделать?
Проверить подключена ли библиотека.
В php.ini должна быть раскоментированна строка
extension=php_zip.dll
пример:
пхпскриптзаходитна фтп в указуную папку, делает фореш файлов и выводит лист пользователю (реализовал) после того как пользователь выбрал файл, тыкает на него, файло качается в тмп папки сервера и передает клиенту (реализовано) для скачки.
но как запачить и выдать на лету этотже фаил клиенту? пытался делать с встроеным зип модулем, но он его сохраняет и не удаляет в последствии из тмп дир сервера! а нужно что бы все что скачалось с фтп сервера удалялось после передачи!
Решение "в лоб".
Написать отдельный скрипт, который будет чистить папку tmp и запускать этот скрипт cron'ом.
А готовый файл менеджер с поддержкой zip на php никто не подскажет? Желательно небольшой.
Заранее благодарен.
Какая именно поддержка zip нужна?
вообщем зделал. но всеравно зип в начале нужно сохранить а потом только удалить!
может еще что подскажите горе програмисту(зачем учится языку програмирования, когда можно посматреть как это делают другие!).
$value ) {$$key=$value;
}
} else {
foreach ( $HTTP_GET_VARS as $key => $value ) {
$$key=$value;
}
}
if (!$lang) {
if (substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2) == 'ru') {
$lang=ru;
} else {
$lang=en;
}
}
require("config.php");
require("lang/".$lang.".php");
// Устанавливаем соединение с FTP-сервером
if ($ftp_server) {
if ($ftp_port) {
if(!$connect = @ftp_connect($ftp_server, $ftp_port)) {
error_mes(LANG_NO_CON);
} else {
if (!$loginOn = @ftp_login($connect, $ftp_user, $ftp_password)) error_mes(LANG_NO_REG);
}
} else {
error_mes(LANG_PORT);
}
} else {
error_mes(LANG_SERVER);
}
// Запрос файла на передачу
if ($get) {
@ftp_chdir($connect, $dir) or error_mes(LANG_ERROR_LOST);
file_get($connect, $get, $tempdir, $dir);
}
// Если нет запроса, то продолжаем вывод списка
$list = @ftp_rawlist($connect, $dir) or error_mes(LANG_ERROR_LOST);
print "";
print "".LANG_NAME."".LANG_SIZE."".LANG_DATA."".LANG_TIME."\n";
list_ftp($list);
@ftp_close($connect) or error_mes(LANG_ERROR_LOST);
print " ";
$time = date("U");
print "$time";
function list_ftp($list)
{
// Получаем все файлы выбранного каталога, указаного в config.php
// Выводим содержимое каталога
foreach($list as $file)
{
// Разбиваем строку по пробельным символам
// Примечание: файлы не могут содержать пробелы в имени
list($acc,
$bloks,
$group,
$user,
$size,
$month,
$day,
$time,
$file) = preg_split("/[\s]+/", $file);
if(substr($acc, 0, 1) == '-')
{
print "";
print "". $file . "";
print "".file_size($size)."";
print "". $month . "," . $day . "";
print "" . $time . "";
print "\n";
}
}
}
// Приобразовываем в нормальный размер
function file_size($size) {
$gb = 1024*1024*1024;
$mb = 1024*1024;
if ($size >= $gb) {$size = sprintf ("%01.2f",$size/$gb) . " GB";}
else if ( $size >= $mb ) {$size = sprintf ("%01.2f",$size/$mb) . " MB";}
else if ( $size >= 1024 ) {$size = sprintf ("%01.2f",$size/1024) . " KB";}
else {$size = $size . " byte";}
return $size;
}
// Вывод ошибок
function error_mes($mes) {
print "Time: ". date("U") ."Message: $mes";
exit;
}
function file_get($connect,$get,$tempdir,$dir) {
$fp = fopen($tempdir . $get, "w");
@ftp_fget($connect, $fp, $get, FTP_BINARY) or error_mes(LANG_ERROR_DOWN);
fclose($fp);
@ftp_close($connect) or error_mes(LANG_ERROR_LOST);
$zip = new ZipArchive;
$zipfile = $get.".zip";
$res = $zip -> open($tempdir . $zipfile, ZIPARCHIVE::CREATE);
$zip -> addFromString("string.txt", "Это строка, которая будет записана в файл string.txt, а сам файл помещен в архив");
// Файл file.txt будет помещен в архив под именем file_zip.txt
$zip -> addFile($tempdir . $get, "$get");
$zip -> close();
header("Content-disposition: attachment; filename=\"$zipfile\"");
header("Content-type: application/octetstream");
readfile($tempdir . $zipfile);
unlink($tempdir . $get);
unlink($tempdir . $zipfile);
exit;
}
?>
так в месте с отладкой и доработкой!
Например, чтобы понять куда вставлять чужой код
Такой вопрос, создаю скриптом архив, количество файлов 7000, после добавления 500 архив закрыть не может, ставлю ограничение на 500 файлов все нормально. memory_limit ставил разные значения исход тот же.
Есть еще параметр из-за которого может возникнуть такая проблема
max_execution_time
Извините про лимит забыл сказать, я поставил в скрипте 3600, с большим запасом, соответственно проблема та же.
Вы работаете с выделенным сервером? Если да, то есть вариант обойти эту проблему. С помощью 7-zip или другого внешнего архиватора. Т.е. запустить его с помощью exec.
по дефолту работа скрипта 30 секунд, если лимит времени привышен, то скрипт ведет себя не коректно! надо прописать лимит на скрипт больше, если того требует время работы скрипта.
Проблему решил, метод конечно очень похож на молоток и напильник, но все же расскажу, может вы меня поправите. В общем, т.к. архив создается после закрытия и мы знаем лимит файлов, можно просто после каждых 500 файлов закрывать архив и снова открывать. Проверил работает, выглядит конечно криво, но по другому не получилось.
Выглядит действительно не очено, но если решение работает и результат устраивает, то смысла переделывать я не вижу. Очень похоже, что проблема в самой библиотеке.
Попробовал немного видоизменить код – свести его в функцию, и архивировать отдельный файл, но ничего не выходит
Сама функция (файл func.php):
function ZIPFile($src_file, $tgt_file){
$zip = new ZipArchive();
if ($zip->open($tgt_file, ZIPARCHIVE::CREATE!==true)) {
print("Ошибка создания архива");
exit(1);
}
$zip->addFile($src_file);
$zip->close();
print("Архив".$tgt_file." создан");
exit(0);
}
пытаюсь вызвать так:
include ("func.php");
$src=".\SourceFile.txt";
$tgt=".\TargetFile.zip";
ZIPFile($src, $tgt);
А какая ошибка при этом появляется?
Ошибка создания архива?
Если да, то нужно проверить может ли вообще скрипт создать этот файл ".\TargetFile.zip"? Попробуйте указать путь полностью.
Все. Попив кофе и отдохнув свежий взгляд нашол косяки.
итак, разбор косяков:
в строке
if ($zip->open($tgt_file, ZIPARCHIVE::CREATE!==true)) {
закрывающая скобка должна стоять перед неравенством т.е. так:
if ($zip->open($tgt_file, ZIPARCHIVE::CREATE)!==true) {
Далее.
обычный косяк оставленный после экспериментов с путями – сделать так:
$src="./SourceFile.txt";
$tgt="./TargetFile.zip";
и все заработало.
Здравствуйте! У меня такой вопрос: Файл в архив добавляется след. образом $zip->addFile($filePath, $fileName). Можно ли в качестве $fileName передавалась строка с русским названием файла в архиве? И если можно, то как?(пробовал просто предать русскую строку но при открытии архива в качестве имён стоят козюбрики). Заранее спасибо за помощь!
Нет, раз у библиотеки есть проблемы с кириллицей, то лучше её не использовать. Если есть много файлов с русскими именами, то можно написать скрипт, который их переименует, например, транслитом.
php_zip.dll – это только для венды, для линукса и уникса совсем по другому
Да, и можно было об этом сказать. Зовется он либо php_zip.so либо просто zip.so
Лежит в /usr/lib/php/modules/
Создал бы кто нибудь нормальный мануал по делению файлов в командной строке Putty по русски с примерами. Мануалы какие то кривые и сложные.
Народ, как сделать так чтобы дотфайл не попадал в архив?
Просто не добавляйте его
В этом примере я получаю файлы из папки с помощью readdir (строка 18). Она вернёт все файлы, находящиеся в папки. Просто вставьте внутрь цикла проверку, и пропускайте ненужные вам файлы.
понял, спасибо.