PHP FTP
FTP в PHP позволяет подключаться к удалённым серверам, загружать и скачивать файлы, управлять директориями с помощью встроенного расширения ext-ftp.
Введение
FTP (File Transfer Protocol) — стандартный сетевой протокол для передачи файлов между клиентом и сервером по TCP-соединению. PHP поставляется со встроенным расширением FTP (ext-ftp), которое позволяет скриптам входить на удалённый сервер и перемещать файлы программно — это удобно для развёртывания ресурсов, синхронизации резервных копий или получения потоков данных с сервера партнёра.
В этой главе рассматривается полный рабочий процесс: подключение, вход в систему, переключение в пассивный режим, загрузка и скачивание файлов, просмотр удалённых файлов и управление ими, а также корректное закрытие соединения. Также объясняются меры безопасности, которые необходимо учитывать перед использованием обычного FTP в производственной среде.
Прежде всего о безопасности. Обычный FTP передаёт имя пользователя, пароль и содержимое файлов в незашифрованном виде. Для конфиденциальных данных используйте
ftp_ssl_connect()(FTP поверх TLS) или предпочтите SFTP (SSH File Transfer Protocol), который расширение FTP не поддерживает — для SFTP используйте расширение PHP SSH2 или библиотеку, например phpseclib.
Типичный рабочий процесс FTP
Каждый FTP-скрипт следует одной и той же структуре, независимо от выполняемой операции:
- Подключение к серверу —
ftp_connect()(илиftp_ssl_connect()для FTPS). - Аутентификация —
ftp_login(). - Настройка — обычно
ftp_pasv($conn, true)для включения пассивного режима. - Передача / управление файлами —
ftp_put(),ftp_get(),ftp_nlist()и др. - Закрытие —
ftp_close().
Подключение к FTP-серверу
Установите соединение с помощью ftp_connect(). Функция принимает имя хоста (а также необязательные порт и таймаут) и возвращает объект FTP\Connection при успехе (ресурс до PHP 8.1) или false при ошибке.
<?php
$conn = ftp_connect("ftp.example.com", 21, 10); // host, port, timeout (seconds)
if ($conn === false) {
die("Could not connect to FTP server");
}
echo "Connected.";Обратите внимание, что подключение не выполняет вход — на этом этапе у вас есть анонимный, неаутентифицированный канал. Перед тем как сервер разрешит выполнять какие-либо полезные действия, необходимо вызвать ftp_login().
Использование FTPS (FTP поверх TLS)
Для шифрования управляющего и информационного каналов замените ftp_connect() на ftp_ssl_connect(). Остальная часть API идентична:
<?php
$conn = ftp_ssl_connect("ftp.example.com");
if ($conn === false) {
die("Could not open a secure FTP connection");
}Вход в систему и пассивный режим
После подключения выполните аутентификацию с помощью ftp_login(). Для публичных серверов, допускающих анонимный доступ, используйте имя пользователя anonymous с паролем в виде адреса электронной почты.
<?php
$conn = ftp_connect("ftp.example.com");
if (!ftp_login($conn, "username", "password")) {
ftp_close($conn);
die("Login failed");
}
// Most networks behind a firewall/NAT require passive mode.
ftp_pasv($conn, true);
echo "Logged in.";Почему важен пассивный режим. В активном режиме сервер открывает соединение данных обратно к вашему клиенту, что межсетевые экраны и NAT-маршрутизаторы почти всегда блокируют. В пассивном режиме клиент сам открывает соединение данных с сервером, что работает за межсетевыми экранами. Как правило, вызывайте ftp_pasv($conn, true) сразу после входа. Его необходимо устанавливать после ftp_login(), а не до.
Загрузка файлов
Используйте ftp_put() для отправки локального файла на сервер. Сигнатура функции: ftp_put($conn, $remote_file, $local_file, $mode), где $mode — это FTP_BINARY или FTP_ASCII.
<?php
$conn = ftp_connect("ftp.example.com");
ftp_login($conn, "username", "password");
ftp_pasv($conn, true);
if (ftp_put($conn, "/public_html/report.pdf", "report.pdf", FTP_BINARY)) {
echo "Upload successful";
} else {
echo "Upload failed";
}
ftp_close($conn);FTP_BINARY или FTP_ASCII. Используйте FTP_BINARY для всего, что не является простым текстом — изображений, PDF-файлов, архивов, исполняемых файлов — поскольку ASCII-режим перезаписывает окончания строк и повредит бинарные данные. Используйте FTP_ASCII только тогда, когда специально требуется преобразование окончаний строк между платформами для текстовых файлов. В сомнительных случаях выбирайте FTP_BINARY — это безопасный вариант по умолчанию.
Для больших файлов можно загружать в неблокирующем режиме с помощью ftp_nb_put(), что позволяет скрипту выполнять другую работу между фрагментами.
Скачивание файлов
ftp_get() сохраняет удалённый файл в локальную файловую систему. Порядок аргументов: ftp_get($conn, $local_file, $remote_file, $mode) — обратите внимание, что локальный путь назначения указывается первым, в отличие от ftp_put(). Путаница с этим — самая распространённая ошибка при работе с FTP.
<?php
$conn = ftp_connect("ftp.example.com");
ftp_login($conn, "username", "password");
ftp_pasv($conn, true);
// local_file first, then remote_file
if (ftp_get($conn, "backup.zip", "/backups/backup.zip", FTP_BINARY)) {
echo "Download successful";
} else {
echo "Download failed";
}
ftp_close($conn);Просмотр удалённых файлов и управление ими
Расширение FTP умеет гораздо больше, чем просто передавать файлы. К распространённым функциям управления относятся:
| Функция | Назначение |
|---|---|
ftp_nlist($conn, $dir) | Массив имён файлов в директории |
ftp_rawlist($conn, $dir) | Детальный листинг в стиле ls -l |
ftp_size($conn, $file) | Размер файла в байтах (-1 при ошибке) |
ftp_mkdir($conn, $dir) | Создать директорию |
ftp_rmdir($conn, $dir) | Удалить (пустую) директорию |
ftp_delete($conn, $file) | Удалить файл |
ftp_rename($conn, $from, $to) | Переименовать / переместить файл |
ftp_chdir($conn, $dir) | Изменить рабочую директорию |
ftp_pwd($conn) | Текущая рабочая директория |
ftp_chmod($conn, 0644, $file) | Изменить права доступа к файлу |
<?php
$conn = ftp_connect("ftp.example.com");
ftp_login($conn, "username", "password");
ftp_pasv($conn, true);
$files = ftp_nlist($conn, "/public_html");
foreach ($files as $file) {
echo $file, " — ", ftp_size($conn, $file), " bytes\n";
}
ftp_close($conn);Закрытие соединения
Всегда освобождайте соединение с помощью ftp_close() по завершении работы. Оборачивание рабочего процесса в try/finally гарантирует закрытие сокета даже при возникновении ошибки:
<?php
$conn = ftp_connect("ftp.example.com");
if (!$conn || !ftp_login($conn, "username", "password")) {
die("Connection or login failed");
}
try {
ftp_pasv($conn, true);
ftp_put($conn, "/public_html/index.html", "index.html", FTP_BINARY);
} finally {
ftp_close($conn);
}Рекомендации и подводные камни
- Предпочитайте FTPS или SFTP. Никогда не передавайте учётные данные через обычный FTP через публичный интернет.
- Всегда включайте пассивный режим (
ftp_pasv), если нет особых причин не делать этого. - Выбирайте правильный режим передачи —
FTP_BINARYдля бинарных данных,FTP_ASCIIтолько для текста, где необходимо преобразование окончаний строк. - Следите за порядком аргументов — в
ftp_putпорядок(remote, local), вftp_get—(local, remote). - Всегда закрывайте соединение с помощью
ftp_close(). - Проверяйте каждое возвращаемое значение. Функции FTP возвращают
falseпри ошибке, а не бросают исключения, поэтому тихие сбои легко пропустить. ext-ftpдолжно быть включено. Проверьте с помощьюextension_loaded('ftp'); если возвращаетсяfalse, включите расширение в вашемphp.ini.
Связанные темы
- Работа с файлами в PHP — чтение и запись локальных файлов.
- Загрузка файлов в PHP — обработка загрузок через HTML-формы.
- Файловая система PHP — расширенный набор функций файловой системы.
- Исключения PHP — структурированная обработка ошибок с
try/finally.