Когда нужно быстро выкачать исходники сайта с сервера, даже относительно быстрый SSH тонель не дает нужной скорости. И ждать приходиться очень и очень долго. А еще многие хостинг провайдеры не предоставляют этого доступа, а заставляют довольствоваться FTP, который в разы медленнее. 

Лично для себя я определил выход. На сервер закачивается небольшой скрипт и запускается. Через некоторое время получаем архив со всеми исходниками. А один файл, даже по древнему FTP качается гораздо быстрее нежели сотня маленьких.

Ранее на страницах этого блога уже упоминалась библиотека zipArchive. Однако, тогда речь шла о распаковке архива. 

Для начала, нам потребуется узнать, есть ли на сервере поддержка zipArchive. Это популярная библиотека установлена на подавляющем числе хостингов.

Библиотека жестко ограничена параметрами php и сервера. Огромные базы и банки фотографий заархивировать не получится. Даже базы старой доброй программы 1С для бухгалтерии. Казалось бы в них должны быть лишь текстовые данные. Но нет. 

Советую использовать библиотеку, лишь при архивировании относительно небольших сайтов, с огромным числом мелких файлов.

Проверим доступна ли работа с библиотекой

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

 

Рассказать друзьям

Добавить комментарий


Защитный код
Обновить

Комментарии   

0
Макс
# Макс 09.10.2015 16:10
Добрый день!
Спасибо за статью, помогло )