Когда нужно быстро выкачать исходники сайта с сервера, даже относительно быстрый SSH тонель не дает нужной скорости. И ждать приходиться очень и очень долго. А еще многие хостинг провайдеры не предоставляют этого доступа, а заставляют довольствоваться FTP, который в разы медленнее.
Лично для себя я определил выход. На сервер закачивается небольшой скрипт и запускается. Через некоторое время получаем архив со всеми исходниками. А один файл, даже по древнему FTP качается гораздо быстрее нежели сотня маленьких.
Ранее на страницах этого блога уже упоминалась библиотека zipArchive. Однако, тогда речь шла о распаковке архива.
Для начала, нам потребуется узнать, есть ли на сервере поддержка zipArchive. Это популярная библиотека установлена на подавляющем числе хостингов.
Библиотека жестко ограничена параметрами php и сервера. Огромные базы и банки фотографий заархивировать не получится. Даже базы старой доброй программы 1С для бухгалтерии. Казалось бы в них должны быть лишь текстовые данные. Но нет.
Советую использовать библиотеку, лишь при архивировании относительно небольших сайтов, с огромным числом мелких файлов.
Проверим доступна ли работа с библиотекой
1 2 3 | if (! extension_loaded ( 'zip' )) { return false; } |
Если все хорошо, скрипт продолжит свое выполнение дальше.
Небольшой оффтоп, для таких проверок. Проверки стоит делать именно так, избегая больших конструкций с вложенными скобками. Так код будет более атомарным, и легко будет поддаваться отладке. Сравните
if ( a==b ){ if ( c==d ){ if ( e==f ){ echo 'Все условия сработали' ; } else echo 'e<>f' ; } else echo 'c<>d' ; } else echo 'a<>b; |
и такой код
if ( a!=b ) exit ('a<>b); if ( c!=d ) exit ('c<>d); if ( e!=f ) exit ('e<>f); echo 'Все условия сработали' ; |
Код приятнее и не разрастается на огромные вложенные конструкции.
Простите за оффтоп, но хотелось поделится этой находкой.
Теперь создадим объект и архив.
$zip = new ZipArchive(); if (! $zip ->open( $destination , ZIPARCHIVE::CREATE)) { return false; } |
где $destination - это полный путь до архива. Если архив уже создан, то файлы будут в него дозаписываться.
Добавление пустой категории происходит так
$zip ->addEmptyDir( str_replace ( $source . '/' , '' , $file . '/' )); |
где $source это полный путь до нашей категории (которую мы изначально архивировали), $file - это полный путь до текущей папки. Это сделано для того, чтобы в архиве не было полных путей, а лишь относительные.
Добавление файла работает похожим образом, но нужно сперва прочитать его в строку.
$zip ->addFromString( str_replace ( $source . '/' , '' , $file ), file_get_contents ( $file )); |
В конце надо закрыть архив.
return $zip ->close(); |
Как пробежать все файлы и поддиректории в папке, думаю объяснять не надо. Погуглите, что-то вроде Рекурсивный обход папок на php
Мне подошел такой вариант
function Zip( $source , $destination ){ if (! extension_loaded ( 'zip' ) || ! file_exists ( $source )) { return false; } $zip = new ZipArchive(); if (! $zip ->open( $destination , ZIPARCHIVE::CREATE)) { return false; } $source = str_replace ( '\\' , '/' , realpath ( $source )); if ( is_dir ( $source ) === true){ $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $source ), RecursiveIteratorIterator::SELF_FIRST); foreach ( $files as $file ){ $file = str_replace ( '\\' , '/' , $file ); // Ignore "." and ".." folders if ( in_array( substr ( $file , strrpos ( $file , '/' )+1), array ( '.' , '..' )) ) continue ; $file = realpath ( $file ); $file = str_replace ( '\\' , '/' , $file ); if ( is_dir ( $file ) === true){ $zip ->addEmptyDir( str_replace ( $source . '/' , '' , $file . '/' )); } else if ( is_file ( $file ) === true){ $zip ->addFromString( str_replace ( $source . '/' , '' , $file ), file_get_contents ( $file )); } } } else if ( is_file ( $source ) === true){ $zip ->addFromString( basename ( $source ), file_get_contents ( $source )); } return $zip ->close(); } |
Комментарии
Спасибо за статью, помогло )