Работаем с FTP

Сегодня мы поговорим о том, как работать с FTP из нашего PHP-скрипта, а кроме этого попытаемся что-нибудь автоматизировать с помощью функций для работы с FTP.

Для начала рассмотрим примеры взаимодействия нашего PHP-скрипта с FTP-сервером. А в качестве задачи выполним следующую - установим для определенной директории и всех вложенных в нее поддиректорий определенные права (например, права на запись), что было бы довольно рутинно, если бы мы ставили эти права вручную через какой-нибудь FTP-менеджер (например, через FAR).

Иногда возникает такая проблема, что нам нужны права на запись для определенной директории, но мы не можем воспользоваться функцией chmod, если скрипт, который ее использует, не был создан под юзером, в котором работает PHP. Проще говоря, если мы заливаем PHP-скрипт на FTP, а затем пытаемся с его помощью установить права 777 на какую-нибудь папку или файл, то PHP говорит нам нечто вроде «Access Denied». Но если бы мы создали этот PHP-скрипт из другого PHP-скрипта, который находится на этом же сервере, то мы могли бы воспользоваться функцией chmod. Но зачастую возникает именно первая ситуация, когда мы скрипты заливаем на FTP вручную, а потом ставим сами необходимые права на определенные папки и файлы (через тот же самый FTP или зайдя на сервер под SSH).

А если нам нужно установить права на все папки в определенной директории, а их там сотни? Причем уровень вложенности = 10, допустим. Тогда руками тут не обойдешься. Придется писать свой скрипт, который рекурсивно будет ставить права. Этим мы и займемся далее.

Итак, часть первая - основы взаимодействия с FTP из PHP.

Рассмотрим пример, в котором будет установлено соединение с FTP, выбор нужной папки на FTP-сервере и закачка файла в эту папку. На моей рабочей машине локально установлен FTP-сервер, поэтому я буду обращаться к нему.

Пусть в корневой директории моего FTP находится поддиректория pub, а в одной директории с моим скриптом находится файл test.txt, который я хочу залить на FTP в директорию pub и установить права на запись на него.

$ftp = ftp_connect('', 21, 30); // соединяемся с локальным FTP (21-ый порт, 30 секунд - таймаут)
if (!empty($ftp)) {
	if (ftp_login($ftp, 'anonymous', '')) { // авторизуемся анонимным юзером
		if (ftp_chdir($ftp, 'pub')) { // меняем текущую директорию на pub
			// пытаемся положить файл test.txt в директорию pub на FTP
			if (!ftp_put($ftp, 'test.txt', 'test.txt', FTP_ASCII)) {
				echo 'Cannot put your file to FTP';
			} else {
				// устанавливаем права на запись для залитого файла
				if (ftp_chmod($ftp, 0777, 'test.txt')) {
					echo 'Everything is OK!';
				} else {
					echo 'Cannot set access rights for test.txt file';
				}
			}
		} else {
			echo 'Cannot find pub directory';
		}
	} else {
		echo 'Cannot login at FTP';
	}
	ftp_close($ftp);
} else {
	echo 'Cannot connect to FTP';
}

Вроде бы тут все предельно ясно. Работа с FTP из PHP не составляет труда. Все функции для работы с FTP описаны в документации по PHP php.net/manual/ru/book.ftp.php

Заметьте, что я не указал первым аргументом адрес FTP-сервера при вызове ftp_connect - это потому что я соединялся со своим локальным FTP. Также я не указал пароль для анонимного пользователя при вызове функции ftp_login - так уж настроен у меня сервер :)

Часть вторая - рекурсивно даем права директориям.

Теперь напишем рекурсивную функцию, которая в указанной директории будет устаналивать права на запись для всех поддиректорий:

ini_set('max_execution_time', '0');
function ftp_is_dir($ftp, $obj) {
	$is_dir = false;
	$cur_dir = ftp_pwd($ftp); // берем путь к текущей директории
	if (@ftp_chdir($ftp, $obj)) {
		ftp_chdir($ftp, $cur_dir);
		$is_dir = true;
	}
	return $is_dir;
}
function ftp_allow_write_for($ftp, $dir, $recursively = true) {
	$success = true;
	$dir = rtrim($dir, '/');
	if (ftp_chmod($ftp, 0777, $dir)) {
		if ($recursively) {
			$pwd = ftp_pwd($ftp);
			ftp_chdir($ftp, $dir);
			$objects = ftp_nlist($ftp, '.'); // перечисляем объекты файловой системы
			ftp_chdir($ftp, $pwd);
			if (is_array($objects)) {
				foreach ($objects as $obj) {
					if ('.' == $obj || '..' == $obj) {
						continue;
					}
					$obj = $dir.'/'.$obj;
					if (ftp_is_dir($ftp, $obj)) { // убеждаемся, что это директория
						if (!ftp_allow_write_for($ftp, $obj, $recursively)) { // даем права
							$success = false;
							$res = 'ERR';
						} else {
							$res = 'OK';
						}
						echo $obj.': '.$res.'';
						ob_flush(); flush();
					}
				}
			} else {
				$success = false;
			}
		}
	} else {
		$success = false;
	}
	return $success;
}
$ftp = ftp_connect('', 21, 30); // соединяемся с локальным FTP (21-ый порт, 30 секунд - таймаут)
if (!empty($ftp)) {
	if (ftp_login($ftp, 'anonymous', '')) { // авторизуемся анонимным юзером
		ftp_pasv($ftp, true); // переведем FTP в пассивный режим (зачастую это требуется)
		if (ftp_allow_write_for($ftp, 'pub')) {
			echo 'Everything is OK!';
		} else {
			echo 'Cannot make this directory writable';
		}
	} else {
		echo 'Cannot login at FTP';
	}
	ftp_close($ftp);
} else {
	echo 'Cannot connect to FTP';
}

Этот скрипт даст права на запись директории pub и всем вложенным поддиректориям. Правда советую запускать такой скрипт с сервера, на котором находится FTP, поскольку скорость работы скрипта в ином случае оставит желать лучшего. Лично я делал так: задал все данные доступа в этом скрипте (адрес FTP-сервера, порт, логин, пароль, корневая директория), скопировал этот скрипт к себе в корневую директорию сайта (на хостинге) и запустил его. Скрипт установил права на запись на нужные мне директории.

Такой скрипт, я думаю, может пригодиться не раз в повседневной работе, так что пользуйтесь и изучайте :)





Читайте также:



9 Ответов на “Работаем с FTP”

  1. В очередной раз спасибо! :)
    Работу с FTP через скрипты на PHP постоянно откладывал по разным причинам “на потом”, но сегодня, за очень короткий срок освоил самое главное!

    p.s.: Каким образом вы подбираете темы для постов? Сколько читаю - 90% информации оказывается актуальной и полезной.

  2. novice

    Если я скажу, каким образом, будет уже не интересно читать :)

  3. Игорь

    Полезная тема.

  4. > Придется писать свой скрипт, который рекурсивно
    > будет ставить права. Этим мы и займемся далее.

    system(‘chmod -R 765 ./dir/*’);

  5. novice

    Правильно. Только очень редко бывает, что есть доступ к всемогущей функции system

  6. s10_

    палезна. как рас искал рекурсивный chmod.
    тока я п тему для блога выбрал не фиксированной ширины )

  7. Рекурсивный chmod… что-то новенькое :)

  8. […] Работа с FTP на PHP требует наличия определенных знаний и навыков. Из основных действий, доступных для работы с FTP-сервером, стоит отметить: соединение с удаленным сервером, регистрация, загрузка файлов (кстати сказать, одна из основных целей применения FTP), а также закрытие соответствующего соединения. Соединения обеспечивает функция ftp_connect (тогда синтаксис будет иметь следующий вид: ftp_connect (string host [, int port [, int timeout]])). Благодаря данной программе работа с файлами осуществляется намного проще и быстрее, а тем более, безопаснее. […]

  9. ф-ция ftp_is_dir забирает очень много ресурсов и захламляет лог-файлы, предлагаю использовать ftp_rawlist, а затем preg_split(“/[\s]+/”, $file); и проверять по ключевым флагам

    А теперь скоростные характеристики:
    1) ftp_nlist + ftp_is_dir
    время работы скрипта - 2.02151894569 cекунд

    2) ftp_rawlist + preg_split(“/[\s]+/”, $file)
    время работы скрипта - 0.369694948196 cекунд


© Copyright. . I-Novice. All Rights Reserved. Terms | Site Map