Перейти к содержимому
Поиск
Php Разработка

PHP: полный мануал с примерами, функциями и ООП

Практический мануал PHP: от переменных и читаемого кода до безопасных форм, интеграций, базы данных и ООП на примере магазина. Учебный маршрут, поиск функций, подробные примеры, разбор ошибок и исходники для скачивания.

Александр НекрасовИзменено:
Практический мануал PHP: от переменных и функций к объектной модели интернет-магазина
PHP 8.5.11149 глав4458 карточек справочника
Дерево руководства

Глава 121 · От файлов к интеграции

FTP: выгрузки, файлы поставщика и полный справочник

Все функции FTP: от подключения до каталогов, передачи, resume, MLSD и серверных команд; с точными границами FTPS/SFTP.

Для чего нужен FTP: две машины и движение файла

Поставщик раз в день кладёт stock.csv в свою папку. Ваш PHP сервис должен забрать файл, проверить строки и обновить остатки. Иногда обратная задача: создать orders.csv и передать его получателю. FTP — протокол работы с удалёнными файлами. Расширение даёт вход, списки, загрузку, скачивание и ограниченный набор операций с каталогами; оно не разбирает CSV и не обновляет базу данных вместо приложения.

Путь выгрузки A42
  1. Поставщик создал incoming/stock.csv
  2. PHP установил соединение и вошёл
  3. GET перенёс байты в локальный .part
  4. Приложение проверило CSV: A42 → 7
  5. Подтверждённая партия попала в импорт
  6. Connection закрыт, результат обработки сохранён
ТерминКонкретный смысл
Локальный файлexport.csv на машине, где запущен PHP. Если PHP работает на сервере, это не файл ноутбука посетителя.
Удалённый файлincoming/stock.csv внутри FTP аккаунта; его путь не обязан совпадать с путём в ОС сервера.
ConnectionОдин сеанс: текущая папка, режим, сетевой timeout.
Control channelКоманды USER/PASS, PWD и ответы сервера. Обычно отдельное TCP соединение к 21.
Data channelОтдельная связь для содержимого файла или списка. Успешный login не доказывает её доступность.
GET / PUTGET: удалённый → локальный. PUT: локальный → удалённый. У функций различается порядок путей.

Для чтения кода понадобятся переменные, аргументы функций и возвращаемое значение, файлы/streams. Текущую задачу начнём с трёх строк: выбрать имя удалённого источника, локальную цель и двоичный режим. При чтении таблицы сигнатуры знак |false означает отдельный результат отказа, а не пустой файл.

Понять два пути до первого подключенияСамостоятельный пример
<?php
declare(strict_types=1);

$remote = 'incoming/stock.csv';
$local = 'stock-copy.csv';
echo "Источник на FTP: ", $remote, "\n";
echo "Цель на PHP машине: ", $local, "\n";
Ожидаемый результат
Источник на FTP: incoming/stock.csv
Цель на PHP машине: stock-copy.csv

Здесь только присваивание и вывод строк; сеть ещё не используется. $ обозначает переменную, = сохраняет строку, ; завершает выражение. Имена source/target помогают не перепутать направления.

FTP, FTPS и SFTP: выбрать нужный договор

Обычный FTP не шифрует пароль или содержимое. FTPS добавляет TLS к FTP, но сохраняет два канала. SFTP — самостоятельный файловый протокол поверх SSH: у него другие клиенты и договор; название «secure FTP» в переписке недостаточно. Уточняйте у партнёра точный протокол, host, port, требования к сертификату/ключу и разрешённый каталог.

ВариантКогда и чем пользоваться
Обычный FTPИзолированная учебная сеть/устаревший согласованный сервис. В примерах — только свой стенд.
Explicit FTPSFTP с AUTH TLS. ftp_ssl_connect существует, но не проверяет peer certificate: для production нужен клиент с проверкой сертификата и имени хоста.
Implicit FTPSШифрование сразу при соединении, обычно 990; не то же поведение, что ftp_ssl_connect.
SFTPSSH File Transfer Protocol, часто 22. Используйте SSH2/SFTP клиент либо поддерживающий его cURL build; смена порта ftp_connect не помогает.
ftp:// wrapperПростое чтение/запись через файловые функции; меньше управления сеансом. Не помещайте пароль в URL, который будет логироваться.
HTTPS API / object storageКогда стороны могут выбрать новый интерфейс, договор об авторизации/повторах/ошибках часто удобнее выразить через готовый HTTP API.

См. cURL и настройка HTTP/сетевого клиента, потоки и wrappers. Ни успешное TCP соединение, ни наличие TLS не доказывает подлинность партнёра без проверки доверия. Это ограничение непосредственно влияет на выбор FTP клиента для реальных данных.

Установка, конфигурация и переход от resource к объекту

FTP — отдельное расширение. На Unix сборка включает --enable-ftp; у пакетного PHP выбирают соответствующий пакет версии. Windows поставляет shared DLL, которую можно включить через ini либо только для отдельного CLI процесса. DLL должна совпасть с версией PHP, архитектурой и TS/NTS. У расширения нет собственного набора runtime INI опций: timeout/AUTOSEEK меняются на конкретном connection.

При Autotools OpenSSL поддержка FTP включается вместе с openssl при --with-openssl; начиная с PHP 8.4 отдельное --with-ftp-ssl позволяет включить FTP TLS без самого расширения openssl. Старый --with-openssl-dir удалён. Наличие ftp_connect ещё не доказывает наличие ftp_ssl_connect. PHP 8.1 заменил прежний ресурс объектом FTP\Connection; это смысл исторического раздела Resource Types.

Проверить возможности загруженного FTP расширенияСамостоятельный пример
<?php
declare(strict_types=1);

echo extension_loaded('ftp') ? "FTP загружено\n" : "Нет FTP\n";
echo class_exists(FTP\Connection::class, false) ? "Класс Connection доступен\n" : "Нет класса\n";
echo function_exists('ftp_ssl_connect') ? "Функция FTPS доступна\n" : "Нет FTPS\n";
Ожидаемый результат
FTP загружено
Класс Connection доступен
Функция FTPS доступна

Ожидаемые строки относятся к PHP 8.5.11 с подходящим расширением FTP/OpenSSL. Проверка не открывает сеть и не проверяет FTP сервер.

Одноразовое включение FTP в CLIФрагмент или команда
php -d extension=ftp example.php

CLI должен найти совместимый модуль в extension_dir; если FTP уже подключён через ini, повторное -d не требуется. Проверяйте php --ini именно у того executable, который будет исполнять задачу.

Учебное окружение и полные вспомогательные файлы

Для примеров с сервером нужна отдельная учебная учётная запись lesson на вашем локальном стенде 127.0.0.1:2121, доступная только для учебных данных. Root аккаунта содержит папки incoming и outgoing; начальный PWD равен /. В incoming хранится только stock.csv с LF переводами строк. Изменяющие примеры используют свои имена lesson-* внутри outgoing. Там, где требуется исходный файл/особая команда, это указано прямо у примера.

Содержимое учебной выгрузки: ровно 14 байтСамостоятельный пример
<?php
declare(strict_types=1);

$csv = "sku,qty\nA42,7\n";
echo $csv;
echo strlen($csv), " байт\n";
Ожидаемый результат
sku,qty
A42,7
14 байт

Сохраните эти две строки в incoming/stock.csv на своём FTP стенде с LF. Код показывает содержимое, но ничего не загружает на сервер. Для CSV в другом формате ожидаемый размер и вывод будут другими.

Пароль задайте через FTP_PASSWORD окружения. FTP_HOST, FTP_PORT, FTP_USER при необходимости меняют адрес/порт/имя своего стенда. Не кладите пароль в открытый репозиторий или публичную папку. Два файла ниже сохраняются рядом с выбранным примером. Они приложены к самостоятельным контекстным примерам; скрытых глобальных подключений нет.

Полный ftp-config.php: настройки учебного стендаПример для указанного окружения
<?php
declare(strict_types=1);

// Only your isolated learning FTP account, never a production root.
$ftpHost = getenv('FTP_HOST') ?: '127.0.0.1';
$ftpPortText = getenv('FTP_PORT') ?: '2121';
if (!ctype_digit($ftpPortText) || (int)$ftpPortText < 1 || (int)$ftpPortText > 65535) {
    throw new RuntimeException('FTP_PORT: число 1…65535');
}
$ftpPort = (int)$ftpPortText;
$ftpUser = getenv('FTP_USER') ?: 'lesson';
$ftpPassword = getenv('FTP_PASSWORD');
if ($ftpPassword === false || $ftpPassword === '') throw new RuntimeException('Задайте FTP_PASSWORD');
if (str_contains($ftpHost, '://') || str_contains($ftpHost, '/')) {
    throw new RuntimeException('Нужно имя узла без схемы и пути');
}

Этот файл проверяет настройки при подключении, но сам не открывает сеть. Значения getenv — строки/false; порт ограничен 1…65535. В production host должен выбираться из доверенной конфигурации, а не произвольного URL запроса. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Полный ftp-lab.php: вход и passiveСамостоятельный пример
<?php
declare(strict_types=1);

function openLessonFtp(): FTP\Connection {
    require __DIR__ . '/ftp-config.php';
    $ftp = ftp_connect($ftpHost, $ftpPort, 5);
    if ($ftp === false) throw new RuntimeException('FTP недоступен');
    try {
        if (!ftp_login($ftp, $ftpUser, $ftpPassword)) throw new RuntimeException('Не выполнен вход');
        if (!ftp_pasv($ftp, true)) throw new RuntimeException('Не включён passive');
        return $ftp;
    } catch (Throwable $error) {
        ftp_close($ftp);
        throw $error;
    }
}
Ожидаемый результат

Файл только объявляет функцию и сам ничего не выводит. openLessonFtp выполняется лишь при её вызове; она возвращает уже настроенный Connection либо бросает исключение, закрыв неудачный сеанс. Получивший connection затем закрывает его в finally.

Граница проверки: примеры без сервера выполнены локально; примеры с FTP командами здесь проходят синтаксическую проверку и помечены «для указанного окружения». Точный успех удалённой операции не заявляется. Это позволяет читать полный договор API, не выдавая наличие синтаксически верного вызова за реальную передачу по сети. После настройки собственного стенда выполняйте нужный сценарий один раз и проверяйте конкретный результат.

Первый полный путь: от соединения к локальному CSV

Первый полезный результат: получить stock.csv на машине PHP и увидеть A42,7. До передачи соединение и пароль проверяются отдельными шагами. Нельзя вызывать login с false после неудачного connect: в PHP 8 это не «ещё одна проверка», а неверный тип аргумента.

Первое полное скачивание без скрытого helperПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-config.php';
$ftp = ftp_connect($ftpHost, $ftpPort, 5);
if ($ftp === false) throw new RuntimeException('Стенд недоступен');
try {
    if (!ftp_login($ftp, $ftpUser, $ftpPassword)) throw new RuntimeException('Вход отклонён');
    if (!ftp_pasv($ftp, true)) throw new RuntimeException('Нет passive');
    if (!ftp_get($ftp, 'lesson-first.csv', 'incoming/stock.csv', FTP_BINARY)) throw new RuntimeException('Файл не получен');
    echo file_get_contents('lesson-first.csv');
} finally { ftp_close($ftp); }
Ожидаемый результат
sku,qty
A42,7

Получившийся файл лежит на PHP машине. try объединяет операции, throw прекращает путь при отказе, finally закрывает connection. Реальный импорт добавит размер/формат/значения/идентификатор партии перед изменением БД. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

СтрокаЗачем здесь нужна
connectСоздаёт сеанс, но ещё не выполняет вход.
loginПредъявляет данные учебной учётной записи.
pasvВыбирает клиентское подключение data channel после входа.
getКопирует байты с удалённого пути в локальный.
echo file_get_contentsПоказывает уже локальный результат.
finally closeОсвобождает сеанс и при успехе, и при throw.

Байты, текст, частичный файл и возобновление

Сохранить фотографию, ZIP или XLSX надо байт в байт: выбирайте FTP_BINARY (он же FTP_IMAGE). ASCII/TEXT предназначен для текстового представления протокола и способен менять переводы строк; это не способ автоматически преобразовать UTF-8 в Windows-1251. Кодировку содержимого и имён согласовывают отдельно. BINARY удобен и для CSV, если обе стороны договорились о точных байтах/LF.

Два независимых указателя при resume
  1. Локальная копия содержит первые 8 байтов
  2. Удалённый файл той же версии ещё доступен
  3. offset=8 задаёт REST источника
  4. AUTOSEEK определяет локальное позиционирование
  5. Дописывается только проверенный остаток
  6. Проверяем целую финальную версию
ПриёмУсловие безопасного применения
FTP_AUTORESUMEДля GET размер локального префикса; для PUT размер удалённой части. Работает с AUTOSEEK и поддержкой REST. Не сравнивает содержимое префикса.
Явный offsetЧисло байтов; требует согласовать и локальную, и удалённую позиции.
AUTOSEEK=falseЛокальный указатель контролируете сами; FTP_AUTORESUME тогда не выполняет автоматический поиск позиции.
Новая версия файлаНе продолжайте старый префикс к новым данным: скачайте отдельную версию заново.
Повтор appendМожет повторно добавить уже принятые строки; нужен протокол дедупликации.

Для атомарной видимости на уровне приложения используйте уникальное имя .part и финальное переименование после проверки. Партнёр должен читать только финальные имена. Атомарность конкретного server-side rename и поведение при существующей цели нужно согласовать; FTP API не даёт общего транзакционного отката.

Состояния, ожидание и стоимость множества запросов

Три состояния неблокирующих функций нельзя заменить словом «успех». FTP_MOREDATA означает активную передачу; FTP_FINISHED — завершение; FTP_FAILED — отказ. Начальный вызов делается один раз, затем continue. Между шагами можно обновлять свой прогресс/проверять общий срок; отдельный background thread не появляется. До завершения stream остаётся открыт, новый transfer на том же connection не запускают.

Управление передачей
  1. ftp_nb_get/put запускает один transfer
  2. Получен статус
  3. MOREDATA → короткая работа приложения → continue
  4. FINISHED → проверка результата
  5. FAILED/false → сохранить контекст и закрыть
  6. Частичный файл не становится готовой выгрузкой

Синхронные FTP операции могут ждать сеть, а тысяча последовательных SIZE/MDTM создаёт тысячу обменов. MLSD часто сокращает число запросов, когда сервер отдаёт нужные facts сразу; это зависит от поддержки и размера каталога. Не называйте nb_* автоматически более быстрым: их цель — дать контроль между шагами, а не повысить пропускную способность.

Полный каталог констант FTP

Все 11 констант раздела FTP. Это не взаимозаменяемые «настройки»: mode, option name, специальная позиция и статус относятся к разным аргументам. Имена доступны только при загруженном расширении. Сравнивайте смысловые константы, не заучивайте их числовые значения.

Константа (int)Роль
FTP_ASCIIТекстовая передача с правилами переводов строк FTP; не перевод кодировки.
FTP_TEXTAlias FTP_ASCII.
FTP_BINARYДвоичная передача, сохраняющая байты; default mode в transfer функциях с PHP 7.3.
FTP_IMAGEAlias FTP_BINARY.
FTP_AUTORESUMEСпециальная позиция автоматического продолжения GET/PUT при включённом AUTOSEEK; не проверка равенства префикса.
FTP_AUTOSEEKИмя bool опции локального seek при resume; default true.
FTP_TIMEOUT_SECИмя int опции положительного сетевого timeout в секундах; default 90 либо connect timeout.
FTP_USEPASVADDRESSИмя bool опции: использовать IP из PASV ответа; false берёт адрес control connection.
FTP_FAILEDЦелый статус неудавшейся неблокирующей передачи.
FTP_FINISHEDЦелый статус завершившейся передачи.
FTP_MOREDATAЦелый статус ещё продолжающейся передачи; нужен continue.
Отделить alias режима от статуса передачиСамостоятельный пример
<?php
declare(strict_types=1);

echo FTP_BINARY === FTP_IMAGE ? "BINARY и IMAGE одинаковы\n" : "Ошибка\n";
echo FTP_ASCII === FTP_TEXT ? "ASCII и TEXT одинаковы\n" : "Ошибка\n";
$state = FTP_MOREDATA;
echo $state === FTP_FINISHED ? "Готово\n" : "Ещё нельзя объявить успех\n";
Ожидаемый результат
BINARY и IMAGE одинаковы
ASCII и TEXT одинаковы
Ещё нельзя объявить успех

Пример не открывает connection; переменная state лишь показывает правило проверки статуса.

Отказы, повторы и границы доверия

Поставщик прислал данные, но соединение разорвалось после загрузки. Был ли файл принят? По одному timeout это не всегда определить. Сохраняйте ID партии, уникальное имя, размер/хеш и стадию обработки; проверяйте ожидаемую цель перед повтором. Не удаляйте входящую выгрузку сразу после начала GET. Иначе временный сбой локальной проверки уничтожит единственный источник.

СимптомЧто проверить по порядку
connect=falseПравильные host/port/протокол; доступность именно с PHP машины; сетевой timeout.
login=falseДанные аккаунта, требования TLS и AUTH, блокировка после попыток.
PWD/MKD работают, GET/LIST зависаютData channel: passive после login, диапазон портов, PASV адрес, firewall/NAT; не менять BINARY на ASCII наугад.
Локальная цель пустая/частичнаяПроверен ли bool transfer; куда указывал локальный путь/stream; правильный порядок аргументов.
Имена обрезались при разборе LISTНе предположен ли универсальный формат split по пробелу; есть ли MLSD.
SIZE/MDTM возвращают -1Функция сервера может отсутствовать; это не размер -1 и не обязательно отсутствие файла.
Недопустимый аргументTypeError/ValueError — исправить код/конфигурацию; повтор в цикле не поможет.

Ошибку отображают пользователю коротко, техническую причину сохраняют без пароля/полного credential URL. Имена файлов — внешние данные: перед локальным сохранением используйте своё назначенное имя и ограниченный каталог. Не исполняйте файл как PHP, не подставляйте имя в SITE EXEC. Отдельная учётная запись импорта получает только необходимые права.

Самостоятельные задания и путь к настоящему импорту

Практика 1: замените A42,7 на B17,3 в отдельной входящей выгрузке и скачайте её в новое локальное имя. Решение: меняется remote_filename у get, после успешного bool читаете локальную цель; параметры не меняются местами. Практика 2: сформируйте CSV в php://temp и отправьте fput. Решение: fputcsv → rewind → fput → fclose. Практика 3: отберите только file записи MLSD с .csv и проверенным размером. Решение: type/name/size проверяются раздельно, cdir/pdir пропускаются.

Практика 4: сервер не поддерживает SIZE. Решение: выбирается явная политика «не импортировать неизвестный объём» либо клиент с ограничением фактически принятых байтов; подмена -1 на 0 запрещена. Практика 5: после успешного PUT назначьте финальное имя через rename, а не сообщайте получателю имя незавершённого .part. Следующий шаг: локальная файловая обработка, массивы строк импорта, транзакция обновления данных.

Функции и методы этой темы

Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.

ftp_connectПолучить соединение с файловым сервером, прежде чем войти и запросить выгрузку.

PHP 4+ · FTP

ftp_connect(string $hostname, int $port = 21, int $timeout = 90): FTP\Connection|false

Получить соединение с файловым сервером, прежде чем войти и запросить выгрузку.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
hostnameИмя узла/IP без схемы и пути.
portПорт FTP, обычно 21; 0 также выбирает 21.
timeoutПоложительные секунды; default 90. Позднее меняется set_option.
РезультатFTP\Connection с PHP 8.1, раньше resource; false при сетевом отказе. Неправильный timeout вызывает ValueError.
Как применяется ftp_connect
  1. Известны host и port
  2. TCP и FTP приветствие
  3. Получен объект
  4. Дальше login
Открыть только управляющее соединениеПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-config.php';
$ftp = ftp_connect($ftpHost, $ftpPort, 5);
if ($ftp === false) throw new RuntimeException('Нет соединения');
echo "Соединение есть; вход ещё не выполнен\n";
ftp_close($ftp);
Ожидаемый результат
Соединение есть; вход ещё не выполнен

Предусловие: свой FTP сервер доступен по FTP_HOST/FTP_PORT. Пять — секунды сетевого ожидания, а не число повторов. Функция читает приветствие сервера, но не проверяет пароль. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Отвергнуть нулевой срок до обращения в сетьСамостоятельный пример
<?php
declare(strict_types=1);

try { ftp_connect('127.0.0.1', 2121, 0); }
catch (ValueError $error) { echo "Таймаут должен быть положительным\n"; }
Ожидаемый результат
Таймаут должен быть положительным

PHP 8.5 проверяет timeout до открытия соединения. Здесь сетевого запроса нет; неверное значение параметра отличается от false при сетевом отказе.

hostname — только имя/IP без ftp://, завершающего / и пути файла. port=0 означает стандартный 21; приложение само проверяет диапазон, не полагаясь на внутреннее приведение short. Timeout должен быть положительным и не превышать допустимую платформенную границу. Он применяется к отдельным сетевым операциям, а не ограничивает суммарный импорт тысячи файлов. Обычный FTP передаёт пароль и данные открыто: учебные примеры ограничены изолированным стендом.

Рядом: ftp_login, ftp_ssl_connect, ftp_close.

ftp_ssl_connectПонять возможности и ограничение встроенного клиента explicit FTPS.

PHP 4.3+ · FTP

ftp_ssl_connect(string $hostname, int $port = 21, int $timeout = 90): FTP\Connection|false

Понять возможности и ограничение встроенного клиента explicit FTPS.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
АргументыТакие же host/port/timeout, как у connect; без схемы.
РезультатСоединение либо false. TLS проверяется только при login.
Критичное ограничениеPeer certificate verification не выполняется. Это не SFTP.
ДоступностьНужна сборка FTP с OpenSSL; объект с PHP 8.1.
Как применяется ftp_ssl_connect
  1. Открыли FTP connection
  2. login отправляет AUTH
  3. Сервер согласовал TLS
  4. Но доверие сертификату API не проверило
Разделить соединение и защищённый входПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-config.php';
$ftp = ftp_ssl_connect($ftpHost, $ftpPort, 5);
if ($ftp === false) throw new RuntimeException('Нет FTP соединения');
try {
    if (!ftp_login($ftp, $ftpUser, $ftpPassword)) throw new RuntimeException('AUTH TLS или вход не удались');
    if (!ftp_pasv($ftp, true)) throw new RuntimeException('Нет passive');
    echo "Сервер принял защищённый вход\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
Сервер принял защищённый вход

Требуется отдельный свой explicit FTPS стенд. ftp_ssl_connect само ещё не доказывает TLS: AUTH выполняется во время login. Эта функция не проверяет сертификат партнёра; пример демонстрирует механизм, а не достаточную защиту производственной интеграции. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Проверить наличие FTPS функции без подключенияСамостоятельный пример
<?php
declare(strict_types=1);

echo function_exists('ftp_ssl_connect') ? "FTPS функция доступна\n" : "Сборка без FTPS\n";
echo "SFTP требует другого клиента\n";
Ожидаемый результат
FTPS функция доступна
SFTP требует другого клиента

Ожидаемый вывод относится к сборке FTP с OpenSSL. Наличие функции не говорит о поддержке TLS выбранным сервером.

Explicit FTPS — FTP с командой AUTH TLS и отдельным data channel, обычно порт 21. SFTP — другой протокол поверх SSH, обычно порт 22; смена числа порта не превращает один протокол в другой. Implicit FTPS на 990 также не тождественен этому API. Для реальной передачи секретов выбирайте клиент с проверкой доверенного CA и имени хоста, например соответствующе настроенный cURL; не отключайте проверку сертификата для «починки». До PHP 7.0 наличие функции сильнее зависело от статической сборки FTP/OpenSSL, особенно Windows.

Рядом: ftp_connect, ftp_login, ftp_pasv.

ftp_loginАвторизовать конкретную учётную запись и только затем перейти к файлам.

PHP 4+ · FTP

ftp_login(FTP\Connection $ftp, string $username, #[\SensitiveParameter] string $password): bool

Авторизовать конкретную учётную запись и только затем перейти к файлам.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
ftpОткрытое connect/ssl_connect соединение.
username/passwordСтроки USER/PASS. SensitiveParameter скрывает пароль в трассировке, но не в вашем собственном логе.
Результатtrue при принятом входе; false и warning при отказе.
После входаОтдельно выбирают passive и проверяют права на нужный каталог.
Как применяется ftp_login
  1. Соединение уже есть
  2. USER/PASS передают учётные данные
  3. Проверяем bool
  4. Только теперь операции с файлами
Войти отдельным шагомПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-config.php';
$ftp = ftp_connect($ftpHost, $ftpPort, 5);
if ($ftp === false) throw new RuntimeException('Нет сервера');
try {
    if (!ftp_login($ftp, $ftpUser, $ftpPassword)) throw new RuntimeException('Сервер отклонил вход');
    echo "Учебная учётная запись принята\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
Учебная учётная запись принята

Имя и пароль не следует хранить в публичном PHP файле, выводить в ошибке или добавлять к URL журнала. Даже принятый пароль не гарантирует право удалить/загрузить файл. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Обработать отказ учебного пароля без раскрытия секретаПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-config.php';
$ftp = ftp_connect($ftpHost, $ftpPort, 5);
if ($ftp === false) throw new RuntimeException('Нет сервера');
try {
    $accepted = @ftp_login($ftp, $ftpUser, 'wrong-lesson-password');
    echo $accepted ? "Неожиданно принят\n" : "Отказ входа: проверьте учебные настройки\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
Отказ входа: проверьте учебные настройки

Единственная намеренно неправильная попытка на своём стенде. @ убирает ожидаемый warning, результат всё равно обработан. В рабочем сервисе ограничивают повторы, иначе можно заблокировать аккаунт. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Рядом: ftp_connect, ftp_pasv, ftp_pwd.

ftp_pasvНастроить направление создания соединения для передачи файлов и списков.

PHP 4+ · FTP

ftp_pasv(FTP\Connection $ftp, bool $enable): bool

Настроить направление создания соединения для передачи файлов и списков.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
enabletrue: passive, false: active; вызывать только после успешного login.
Результатbool; отказ надо обработать до операции с данными.
Два каналаУспех login/PWD/MKD ещё не означает доступность LIST/GET/PUT: им нужен data channel.
Как применяется ftp_pasv
  1. Login прошёл
  2. PASV сообщает адрес данных
  3. Клиент соединяется к нему
  4. Передача использует отдельный канал
Клиент открывает data channelПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
if (!ftp_pasv($ftp, true)) throw new RuntimeException('Не включён passive');
echo "Для данных используется passive
";
} finally { ftp_close($ftp); }
Ожидаемый результат
Для данных используется passive

openLessonFtp уже входит и включает passive; повторный вызов здесь показывает именно настройку. В passive соединение данных инициирует клиент, что обычно удобнее за NAT. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Учесть неверный PASV адрес старого стендаПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
ftp_set_option($ftp, FTP_USEPASVADDRESS, false);
if (!ftp_pasv($ftp, true)) throw new RuntimeException('Нет passive');
$names = ftp_nlist($ftp, 'incoming');
if ($names === false) throw new RuntimeException('Data channel не открылся');
echo "Список получен через адрес управляющего соединения
";
} finally { ftp_close($ftp); }
Ожидаемый результат
Список получен через адрес управляющего соединения

Применять только к известной проблеме конфигурации PASV сервера за NAT. Это не универсальное ускорение и не снятие firewall; правильнее исправить объявляемый адрес и диапазон passive портов у администратора. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Рядом: ftp_login, ftp_set_option, ftp_nlist.

ftp_closeОсвободить соединение и завершить FTP сеанс.

PHP 4+ · FTP

ftp_close(FTP\Connection $ftp): bool

Освободить соединение и завершить FTP сеанс.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
ftpЖивое соединение.
Результатbool по договору API. После закрытия требуется новый connect.
Aliasquit и close выполняют одну операцию; не вызывайте оба.
Как применяется ftp_close
  1. Операции завершены
  2. finally выполняет ftp_close
  3. Endpoint закрыт
  4. Переменная больше не годится для FTP
Закрыть учебное соединениеПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
echo ftp_close($ftp) ? "Соединение закрыто\n" : "Отказ закрытия\n";
Ожидаемый результат
Соединение закрыто

В этом примере операция закрытия — последняя. Объект может ещё находиться в переменной, но связь им уже не представлена. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Закрыть соединение после успешного чтения или ошибкиПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
    $directory = ftp_pwd($ftp);
    if ($directory === false) throw new RuntimeException('Нет каталога');
    echo "Каталог прочитан\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
Каталог прочитан

finally выполняется и после throw. Не вызывайте close второй раз через другую переменную, ссылающуюся на тот же FTP\Connection. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Закрывайте соединение после пачки операций, а не создавайте новое ради каждого метаданного. Повторное обращение к закрытому объекту в PHP 8.5 приводит к ValueError. Close не откатывает уже отправленные байты, создание каталога или удаление файла.

Рядом: ftp_connect, ftp_quit.

ftp_quitОсвободить соединение и завершить FTP сеанс.

PHP 4+ · FTP

ftp_quit(FTP\Connection $ftp): bool

Освободить соединение и завершить FTP сеанс.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
ftpЖивое соединение.
Результатbool по договору API. После закрытия требуется новый connect.
Aliasquit и close выполняют одну операцию; не вызывайте оба.
Как применяется ftp_quit
  1. Операции завершены
  2. finally выполняет ftp_quit
  3. Endpoint закрыт
  4. Переменная больше не годится для FTP
Закрыть учебное соединениеПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
echo ftp_quit($ftp) ? "Соединение закрыто\n" : "Отказ закрытия\n";
Ожидаемый результат
Соединение закрыто

В этом примере операция закрытия — последняя. Объект может ещё находиться в переменной, но связь им уже не представлена. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Закрыть соединение после успешного чтения или ошибкиПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
    $directory = ftp_pwd($ftp);
    if ($directory === false) throw new RuntimeException('Нет каталога');
    echo "Каталог прочитан\n";
} finally { ftp_quit($ftp); }
Ожидаемый результат
Каталог прочитан

finally выполняется и после throw. Не вызывайте close второй раз через другую переменную, ссылающуюся на тот же FTP\Connection. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

ftp_quit является точным alias ftp_close; выбирать можно привычное имя. Повторное обращение к закрытому объекту в PHP 8.5 приводит к ValueError. Close не откатывает уже отправленные байты, создание каталога или удаление файла.

Рядом: ftp_connect, ftp_close.

ftp_get_optionПрочитать настройки именно этого FTP соединения.

PHP 4.2+ · FTP

ftp_get_option(FTP\Connection $ftp, int $option): int|bool

Прочитать настройки именно этого FTP соединения.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
optionFTP_TIMEOUT_SEC → int; FTP_AUTOSEEK/FTP_USEPASVADDRESS → bool. Третья опция поддержана реализацией, хотя в старой таблице PHP.net пропущена.
ОшибкаPHP 8.5: неизвестное имя/число опции — ValueError; закрытое соединение — ValueError.
Как применяется ftp_get_option
  1. Есть настроенное соединение
  2. Выбран смысл опции
  3. Получили int или bool
  4. false для bool означает выключено
Узнать сетевой timeout выбранного соединенияПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
echo ftp_get_option($ftp, FTP_TIMEOUT_SEC), " секунд\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
5 секунд

В helper timeout задан при connect равным пяти. Значение не относится ко всему импорту и не задаёт срок выполнения PHP процесса. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Различить выключенную опцию и ошибку выбораПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
ftp_set_option($ftp, FTP_AUTOSEEK, false);
echo ftp_get_option($ftp, FTP_AUTOSEEK) === false ? "Автопозиционирование выключено\n" : "Включено\n";
try { ftp_get_option($ftp, -123); }
catch (ValueError $error) { echo "Неизвестная опция\n"; }
} finally { ftp_close($ftp); }
Ожидаемый результат
Автопозиционирование выключено
Неизвестная опция

Текущее PHP 8.5 поведение уточнено по исходникам: неизвестная опция бросает ValueError. Старое описание warning/false нельзя смешивать с корректным bool false выключенной опции. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Рядом: ftp_set_option, ftp_connect.

ftp_set_optionИзменить timeout, позиционирование или адрес passive без переоткрытия соединения.

PHP 4.2+, true return PHP 8.5 · FTP

ftp_set_option(FTP\Connection $ftp, int $option, int|bool $value): true

Изменить timeout, позиционирование или адрес passive без переоткрытия соединения.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
option/valueДопустимые три сочетания перечислены ниже.
РезультатPHP 8.5: true; раньше сигнатура bool.
ОшибкиTypeError при неподходящем типе value, ValueError при неизвестной опции, неверном timeout или закрытом объекте.
Как применяется ftp_set_option
  1. Выбрали option
  2. Проверили тип value
  3. Соединение сохраняет настройку
  4. Следующая операция её использует
Задать timeout для следующих сетевых операцийПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
ftp_set_option($ftp, FTP_TIMEOUT_SEC, 8);
echo ftp_get_option($ftp, FTP_TIMEOUT_SEC), " секунд\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
8 секунд

Это изменение уже открытого connection. Более длинный timeout не чинит неверный путь, права или firewall. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Не путать 0/1 и настоящие bool в настройкахПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
try { ftp_set_option($ftp, FTP_AUTOSEEK, 1); }
catch (TypeError $error) { echo "Для AUTOSEEK требуется bool\n"; }
ftp_set_option($ftp, FTP_AUTOSEEK, true);
echo "Автопозиционирование включено\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
Для AUTOSEEK требуется bool
Автопозиционирование включено

Value типизируется по option. В PHP 8.5 возвращается true либо выбрасывается ошибка; не рассчитывайте получить false для неверных настроек. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

ОпцияЗначение / default
FTP_TIMEOUT_SECint > 0, default 90 либо timeout из connect; есть верхняя системная граница.
FTP_AUTOSEEKbool, default true; при resume автоматически перемещает локальный указатель.
FTP_USEPASVADDRESSbool, default true; false игнорирует IP в PASV ответе и берёт IP управляющего подключения.

Рядом: ftp_get_option, ftp_pasv.

FTP\ConnectionОтличать PHP объект соединения от адреса сервера и обычного класса приложения.

PHP 8.1+ · FTP

final class FTP\Connection {}

Отличать PHP объект соединения от адреса сервера и обычного класса приложения.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
СозданиеТолько фабрики connect/ssl_connect; нельзя new/clone/serialize как обычную запись.
Свойства и методыПубличного пользовательского интерфейса нет; состояние хранится внутри расширения.
ВерсияС PHP 8.1 вместо FTP resource.
Как применяется FTP\Connection
  1. Фабрика открыла connection
  2. Объект хранит сеанс
  3. ftp_* используют тот же первый аргумент
  4. close завершает владение
Получить непрозрачный объект фабрикойПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
echo $ftp instanceof FTP\Connection ? "Это FTP connection\n" : "Другой объект\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
Это FTP connection

Connection не предоставляет методов get/put. Его передают первым аргументом процедурных ftp_* функций; это пример внутреннего класса без пользовательского API методов. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Не создавать неинициализированное соединение через newСамостоятельный пример
<?php
declare(strict_types=1);

try { $ftp = new FTP\Connection(); }
catch (Error $error) { echo "Используйте ftp_connect или ftp_ssl_connect\n"; }
Ожидаемый результат
Используйте ftp_connect или ftp_ssl_connect

Ни сеть, ни пароль в этом примере не используются. Внутренний final класс создаётся фабриками; сериализация для передачи соединения в другой процесс не поддерживается.

Рядом: ftp_connect, ftp_close.

ftp_pwdУзнать базу относительных удалённых путей.

PHP 4+ · FTP

ftp_pwd(FTP\Connection $ftp): string|false

Узнать базу относительных удалённых путей.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
ftpСоединение после входа.
РезультатУдалённый current directory либо false; не путь файловой системы локальной машины.
Как применяется ftp_pwd
  1. Вошли в учётную запись
  2. PWD запрашивает текущий каталог
  3. Сохранили строку
  4. При необходимости вернули через chdir
Узнать исходный каталог учётной записиПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$directory = ftp_pwd($ftp);
if ($directory === false) throw new RuntimeException('PWD не выполнен');
echo $directory, "\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
/

Ожидается / на описанном учебном стенде. Другой сервер вправе вернуть иной виртуальный путь. Это не локальный getcwd PHP. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Временно сменить каталог и восстановить исходныйПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$previous = ftp_pwd($ftp);
if ($previous === false) throw new RuntimeException('Неизвестно, куда возвращаться');
try {
    if (!ftp_chdir($ftp, 'incoming')) throw new RuntimeException('Нет incoming');
    echo "Работа внутри incoming\n";
} finally {
    if (!ftp_chdir($ftp, $previous)) throw new RuntimeException('Не восстановлен каталог');
}
} finally { ftp_close($ftp); }
Ожидаемый результат
Работа внутри incoming

Состояние текущего каталога принадлежит соединению. Другие функции, которым передали тот же объект, увидят смену каталога; сохранение/восстановление ограничивает этот побочный эффект. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Рядом: ftp_chdir, ftp_cdup.

ftp_chdirСменить рабочую папку удалённого сеанса перед группой операций.

PHP 4+ · FTP

ftp_chdir(FTP\Connection $ftp, string $directory): bool

Сменить рабочую папку удалённого сеанса перед группой операций.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
directoryУдалённый относительный/абсолютный путь.
Результатtrue либо false; при отказе также warning.
Побочный эффектИзменяется база последующих relative путей в этом соединении.
Как применяется ftp_chdir
  1. Сейчас /
  2. chdir incoming
  3. Теперь /incoming
  4. stock.csv означает /incoming/stock.csv
Перейти к входящей выгрузкеПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
if (!ftp_chdir($ftp, 'incoming')) throw new RuntimeException('Нет доступа к incoming');
echo ftp_pwd($ftp), "\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
/incoming

Путь relative к текущему FTP каталогу. Абсолютный /incoming относится к виртуальному корню аккаунта, который может быть отделён chroot от реального корня ОС. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Читать имя файла относительно выбранной папкиПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
if (!ftp_chdir($ftp, '/incoming')) throw new RuntimeException('Нет папки');
$size = ftp_size($ftp, 'stock.csv');
if ($size < 0) throw new RuntimeException('Размер не получен');
echo $size > 0 ? "В папке есть непустая выгрузка\n" : "Выгрузка пуста\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
В папке есть непустая выгрузка

Параметр не является URL и не требует urlencode. Разрешённые каталоги определяет ваш договор; не подставляйте в chdir произвольное поле из HTML формы. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Рядом: ftp_pwd, ftp_cdup.

ftp_cdupПодняться ровно на один уровень удалённого дерева каталогов.

PHP 4+ · FTP

ftp_cdup(FTP\Connection $ftp): bool

Подняться ровно на один уровень удалённого дерева каталогов.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
Результатtrue/false, состояние каталога меняется при успехе.
ГраницаРодитель определяется FTP сервером; это не локальная dirname и не обход ограничения аккаунта.
Как применяется ftp_cdup
  1. Текущий /incoming
  2. CDUP
  3. Текущий /
  4. Можно выбрать соседнюю папку
Вернуться из incoming в родительский каталогПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
if (!ftp_chdir($ftp, '/incoming')) throw new RuntimeException('Нет incoming');
if (!ftp_cdup($ftp)) throw new RuntimeException('Не выполнен CDUP');
echo ftp_pwd($ftp), "\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
/

Это один уровень вверх, а не возврат к каталогу, с которого начиналась произвольная операция. На корне результат зависит от политики сервера. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

После просмотра вложенной папки перейти к соседнейПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
if (!ftp_chdir($ftp, '/incoming')) throw new RuntimeException('Нет incoming');
if (!ftp_cdup($ftp)) throw new RuntimeException('Нет родителя');
if (!ftp_chdir($ftp, 'outgoing')) throw new RuntimeException('Нет соседней папки');
echo ftp_pwd($ftp), "\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
/outgoing

Для реального обхода дерева храните исходный путь и глубину, ограничивайте рекурсию. CDUP не обещает доступ выше корня аккаунта. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Рядом: ftp_chdir, ftp_pwd.

ftp_mkdirСоздать именованное место для новой партии файлов.

PHP 4+ · FTP

ftp_mkdir(FTP\Connection $ftp, string $directory): string|false

Создать именованное место для новой партии файлов.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
directoryОдна новая удалённая папка; родитель должен существовать.
РезультатСтрока имени созданного каталога либо false.
ОшибкиWarning при существующем имени, отсутствии прав и прочем отказе.
Как применяется ftp_mkdir
  1. outgoing уже существует
  2. MKD lesson-new
  3. Сервер вернул путь
  4. Туда можно загрузить партию
Создать отдельную папку своей выгрузкиПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$created = ftp_mkdir($ftp, 'outgoing/lesson-new');
if ($created === false) throw new RuntimeException('Не создан каталог');
echo "Папка создана\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
Папка создана

Предусловие: outgoing существует, lesson-new ещё нет, пользователь имеет право создания. Это одна папка; отсутствующие родители не создаются автоматически. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Не путать строку результата с boolПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$created = ftp_mkdir($ftp, 'outgoing/lesson-batch');
if ($created === false) throw new RuntimeException('MKD отклонён');
echo is_string($created) ? "Сервер вернул имя нового каталога\n" : "Неверный тип\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
Сервер вернул имя нового каталога

Не проверяйте $created === true: успешный результат — строка пути. Повторный запуск с тем же именем обычно выдаст warning/false, а не «каталог теперь точно наш». Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Рядом: ftp_rmdir, ftp_chdir.

ftp_rmdirУдалить известный пустой каталог после окончания своей работы.

PHP 4+ · FTP

ftp_rmdir(FTP\Connection $ftp, string $directory): bool

Удалить известный пустой каталог после окончания своей работы.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
directoryАбсолютный/относительный путь пустой папки.
Результатtrue/false; рекурсивной очистки нет.
ПрактикаУдаляют только каталог, владельцем и назначением которого управляет задача.
Как применяется ftp_rmdir
  1. Создали собственную папку
  2. Убедились в её назначении
  3. RMD удалил пустую папку
  4. Чужие файлы не затронуты
Удалить только собственную пустую учебную папкуПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$name = 'outgoing/lesson-empty';
if (ftp_mkdir($ftp, $name) === false) throw new RuntimeException('Учебная папка не создана');
if (!ftp_rmdir($ftp, $name)) throw new RuntimeException('Пустая папка не удалена');
echo "Учебная пустая папка убрана\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
Учебная пустая папка убрана

Папку сначала создаёт сам пример; если она уже существовала, выполнение прекращается до удаления. Функция не выполняет рекурсивное удаление. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Не превращать неудачное rmdir в очистку всех вложенных файловПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$name = 'outgoing/lesson-filled';
if (ftp_mkdir($ftp, $name) === false) throw new RuntimeException('Папка не создана');
$file = fopen('php://temp', 'w+b');
if ($file === false) throw new RuntimeException('Нет буфера');
try {
    fwrite($file, 'A42'); rewind($file);
    if (!ftp_fput($ftp, $name . '/keep.txt', $file)) throw new RuntimeException('Нет файла');
    echo @ftp_rmdir($ftp, $name) ? "Неожиданное удаление\n" : "Непустая папка сохранена\n";
} finally { fclose($file); }
} finally { ftp_close($ftp); }
Ожидаемый результат
Непустая папка сохранена

Остаются созданные примером папка/keep.txt для ручного осмотра. false может означать и отсутствие прав; функция не сообщает надёжно единственную причину. Не добавляйте автоматическое delete по всему серверу. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Рядом: ftp_mkdir, ftp_delete.

ftp_deleteУдалить конкретный удалённый файл по явному решению приложения.

PHP 4+ · FTP

ftp_delete(FTP\Connection $ftp, string $filename): bool

Удалить конкретный удалённый файл по явному решению приложения.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
filenameОдин удалённый файл, не локальная копия и не каталог.
Результатtrue/false; корзины и транзакционного отката API не предоставляет.
Как применяется ftp_delete
  1. Известен свой временный путь
  2. DELE запрашивает удаление
  3. Проверяем bool
  4. Файл исчезает у сервера
Убрать известный временный файл своей операцииПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$stream = fopen('php://temp', 'w+b');
if ($stream === false) throw new RuntimeException('Нет буфера');
try {
    fwrite($stream, 'temporary'); rewind($stream);
    if (!ftp_fput($ftp, 'outgoing/lesson-delete.tmp', $stream)) throw new RuntimeException('Не загружено');
    if (!ftp_delete($ftp, 'outgoing/lesson-delete.tmp')) throw new RuntimeException('Не удалено');
    echo "Временный файл удалён\n";
} finally { fclose($stream); }
} finally { ftp_close($ftp); }
Ожидаемый результат
Временный файл удалён

Предусловие: выделенный путь не используется другим процессом. Права на загрузку и удаление могут различаться. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Принять решение об удалении по списку своих экспортовПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$owned = ['outgoing/lesson-expired.csv'];
$requested = 'outgoing/lesson-expired.csv';
if (!in_array($requested, $owned, true)) throw new RuntimeException('Чужой путь');
if (!ftp_delete($ftp, $requested)) throw new RuntimeException('Удаление не подтверждено');
echo "Удалён только разрешённый экспорт\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
Удалён только разрешённый экспорт

Требуется заранее созданный учебный lesson-expired.csv. Имя из HTTP запроса само по себе не является разрешением. Для скачивания поставщика сначала сохраняют и проверяют локальную копию, затем отмечают обработку; ранний delete способен потерять данные. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Рядом: ftp_rmdir, ftp_rename.

ftp_renameСменить имя или путь файла/каталога после изменения стадии обработки.

PHP 4+ · FTP

ftp_rename(FTP\Connection $ftp, string $from, string $to): bool

Сменить имя или путь файла/каталога после изменения стадии обработки.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
from/toСуществующий источник и новая удалённая цель.
Результатtrue/false; failure сопровождается warning.
ОграничениеУсловия перезаписи, атомарности и переноса определяет сервер.
Как применяется ftp_rename
  1. Пишем .part
  2. Передача завершилась
  3. RNFR/RNTO меняют имя
  4. Получатель видит .csv
Показать готовый файл только после успешной передачиПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$stream = fopen('php://temp', 'w+b');
if ($stream === false) throw new RuntimeException('Нет буфера');
try {
    fwrite($stream, "sku,qty\nA42,7\n"); rewind($stream);
    if (!ftp_fput($ftp, 'outgoing/lesson-ready.part', $stream)) throw new RuntimeException('Передача не завершена');
    if (!ftp_rename($ftp, 'outgoing/lesson-ready.part', 'outgoing/lesson-ready.csv')) throw new RuntimeException('Переименование не выполнено');
    echo "Финальное имя назначено после передачи\n";
} finally { fclose($stream); }
} finally { ftp_close($ftp); }
Ожидаемый результат
Финальное имя назначено после передачи

Получатель должен игнорировать .part; пути принадлежат одной учебной задаче. Атомарность замены/перезапись существующей цели зависят от сервера и файловой системы — одна функция не обещает универсальную транзакцию. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Переименовать созданную папку партииПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
if (ftp_mkdir($ftp, 'outgoing/lesson-draft') === false) throw new RuntimeException('Папка не создана');
if (!ftp_rename($ftp, 'outgoing/lesson-draft', 'outgoing/lesson-approved')) throw new RuntimeException('Папка не переименована');
echo "Название партии изменено\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
Название партии изменено

ftp_rename подходит и файлам, и каталогам. Не предполагайте возможность перенести между разными файловыми системами/учётными корнями. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Рядом: ftp_put, ftp_delete.

ftp_chmodИзменить серверные Unix-права файла там, где FTP сервер это поддерживает.

PHP 5+ · FTP

ftp_chmod(FTP\Connection $ftp, int $permissions, string $filename): int|false

Изменить серверные Unix-права файла там, где FTP сервер это поддерживает.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
permissionsВосьмеричная маска, например 0644/0600; не строка и не десятичные 644.
filenameУдалённый путь файла.
РезультатНовое числовое permissions либо false; проверять строго.
ДоступностьНужна поддержка SITE CHMOD и полномочия аккаунта.
Как применяется ftp_chmod
  1. Выбран учебный файл
  2. Определена нужная маска
  3. SITE CHMOD отправлен
  4. Строго проверили результат
Разрешить владельцу запись и остальным чтениеПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$permissions = ftp_chmod($ftp, 0644, 'outgoing/lesson-permissions.txt');
if ($permissions === false) throw new RuntimeException('CHMOD не поддержан или запрещён');
echo decoct($permissions), "\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
644

Нужен заранее созданный свой файл и сервер с SITE CHMOD. Восьмеричная запись 0644 означает owner rw, group/other r. Десятичное 644 имеет другое числовое значение. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Ограничить чтение учебного отчёта владельцемПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$result = ftp_chmod($ftp, 0600, 'outgoing/lesson-private.txt');
if ($result === false) throw new RuntimeException('Права не изменены');
echo $result === 0600 ? "Запрошены права владельца\n" : "Иной результат\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
Запрошены права владельца

Требуется свой файл. Unix mode не заменяет ACL, политику FTP и шифрование канала. Возвращённое число отражает успешную команду, а не независимый аудит всех способов доступа. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Рядом: ftp_site, ftp_rawlist.

ftp_getПолучить удалённый файл и сохранить его по локальному пути.

PHP 4+ · FTP

ftp_get(FTP\Connection $ftp, string $local_filename, string $remote_filename, int $mode = FTP_BINARY, int $offset = 0): bool

Получить удалённый файл и сохранить его по локальному пути.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
local_filenameЛокальная цель; существующий файл может быть перезаписан.
remote_filenameУдалённый источник. У get порядок отличается от put.
modeFTP_BINARY по умолчанию с PHP 7.3; FTP_ASCII только когда нужен перевод строк протокола.
offsetУдалённая стартовая позиция; 0 — сначала, FTP_AUTORESUME при AUTOSEEK для resume.
Результатtrue только при завершённой передаче, иначе false.
Как применяется ftp_get
  1. Сервер хранит stock.csv
  2. GET читает данные
  3. Локальный .part наполняется
  4. Проверка → финальная копия
Скачать CSV поставщика в локальный файлПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
if (!ftp_get($ftp, 'stock-copy.csv', 'incoming/stock.csv', FTP_BINARY)) {
    throw new RuntimeException('Файл не скачан целиком');
}
echo file_get_contents('stock-copy.csv');
} finally { ftp_close($ftp); }
Ожидаемый результат
sku,qty
A42,7

Удалённый incoming/stock.csv имеет содержимое из начала главы. stock-copy.csv создаётся рядом с запускаемым скриптом: это файл сервера PHP, не папка Downloads браузера. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Не выдавать неполное скачивание за финальный файлПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$partial = 'lesson-stock.part';
$final = 'lesson-stock.csv';
if (!ftp_get($ftp, $partial, 'incoming/stock.csv', FTP_BINARY)) throw new RuntimeException('Загрузка не завершена');
$input = fopen($partial, 'rb');
if ($input === false) throw new RuntimeException('Нет локальной копии');
try {
    $header = fgetcsv($input, null, ',', '"', '');
    if ($header !== ['sku', 'qty']) throw new RuntimeException('Неправильный заголовок');
} finally { fclose($input); }
if (!rename($partial, $final)) throw new RuntimeException('Локальное переименование не выполнено');
echo "Локальная выгрузка прошла проверку заголовка\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
Локальная выгрузка прошла проверку заголовка

Выделенные пути принадлежат этой задаче. Проверка заголовка показана как первая ступень; она не проверяет каждую строку, подпись или идентичность версии выгрузки. При failure .part может остаться для диагностики. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

local_filename может быть перезаписан. При сетевом отказе после открытия цели синхронный ftp_get в PHP 8.5 закрывает и удаляет локальный файл; при отказе самого открытия прежний файл может сохраниться, а аварийно прерванный процесс способен оставить частичный. Поэтому используйте отдельное имя .part, а не единственную рабочую копию. offset задаёт позицию удалённого источника; при включённом AUTOSEEK затрагивается и локальное позиционирование. Возобновляйте только неизменившийся бинарный файл, чей уже сохранённый префикс проверен. Размер/mtime сами по себе не доказывают равенство данных; договор об immutable версии или хеше надёжнее.

Рядом: ftp_fget, ftp_nb_get, ftp_put.

ftp_fgetЗаписать скачиваемые байты в уже открытый локальный stream.

PHP 4+ · FTP

ftp_fget(FTP\Connection $ftp, resource $stream, string $remote_filename, int $mode = FTP_BINARY, int $offset = 0): bool

Записать скачиваемые байты в уже открытый локальный stream.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
streamОткрытый на запись stream; сохраняется у вызывающего кода.
remote_filename/mode/offsetИсточник, двоичный/ASCII режим, позиция в удалённом файле.
Результатtrue/false; не строка данных. При записи остаётся частичный результат, если связь оборвалась.
AUTOSEEKПри resume управляет автоматическим seek локального stream.
Как применяется ftp_fget
  1. Открыли php://temp
  2. FGET пишет байты
  3. rewind возвращает указатель
  4. Читаем CSV и закрываем stream
Получить CSV в открытый временный streamПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$stream = fopen('php://temp', 'w+b');
if ($stream === false) throw new RuntimeException('Нет stream');
try {
    if (!ftp_fget($ftp, $stream, 'incoming/stock.csv', FTP_BINARY)) throw new RuntimeException('Не скачано');
    rewind($stream);
    echo stream_get_contents($stream);
} finally { fclose($stream); }
} finally { ftp_close($ftp); }
Ожидаемый результат
sku,qty
A42,7

ftp_fget пишет в переданный stream и не возвращает его содержимое строкой. После записи указатель переместился, поэтому перед чтением нужен rewind. Владелец stream закрывает его сам. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Явно получить только суффикс известной версии файлаПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$stream = fopen('php://temp', 'w+b');
if ($stream === false) throw new RuntimeException('Нет stream');
try {
    ftp_set_option($ftp, FTP_AUTOSEEK, false);
    if (!ftp_fget($ftp, $stream, 'incoming/stock.csv', FTP_BINARY, 8)) throw new RuntimeException('REST/GET не выполнен');
    rewind($stream);
    echo stream_get_contents($stream);
} finally { fclose($stream); }
} finally { ftp_close($ftp); }
Ожидаемый результат
A42,7

Серверный файл начинается ровно с восьми ASCII байтов sku,qty и LF; сервер должен поддержать REST. AUTOSEEK выключен: локальный пустой stream пишет с текущей позиции 0, удалённый читает с 8. Это демонстрация двух разных указателей, не универсальный способ пропустить CSV заголовок. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Рядом: ftp_get, ftp_nb_fget, ftp_fput.

ftp_putПередать локальный файл в удалённый каталог поставщика/получателя.

PHP 4+ · FTP

ftp_put(FTP\Connection $ftp, string $remote_filename, string $local_filename, int $mode = FTP_BINARY, int $offset = 0): bool

Передать локальный файл в удалённый каталог поставщика/получателя.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
remote_filenameУдалённая цель, которая может быть перезаписана.
local_filenameСуществующий читаемый локальный файл PHP машины.
modeBINARY сохраняет байты ZIP/изображения/CSV; ASCII меняет представление переводов строк.
offsetПозиция удалённой цели для resume, 0 сначала; AUTOSEEK влияет на локальное чтение.
Результатtrue/false; неполная цель может остаться после отказа.
Как применяется ftp_put
  1. export.csv создан локально
  2. PUT открывает data channel
  3. Байты передаются
  4. Проверяем завершение/приём
Отправить локально подготовленный CSVПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
if (!ftp_put($ftp, 'outgoing/lesson-upload.csv', 'export.csv', FTP_BINARY)) throw new RuntimeException('Передача не завершена');
echo "CSV передан\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
CSV передан

export.csv лежит рядом с примером и приложен ниже; outgoing существует на стенде. Второй аргумент — удалённое имя, третий — локальный файл. Браузерное имя $_FILES[name] не заменяет серверный путь $_FILES[tmp_name]. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Проверить ожидаемый объём после передачиПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$local = 'export.csv';
$remote = 'outgoing/lesson-size.csv';
$expected = filesize($local);
if ($expected === false) throw new RuntimeException('Нет локального размера');
if (!ftp_put($ftp, $remote, $local, FTP_BINARY)) throw new RuntimeException('Не передано');
$actual = ftp_size($ftp, $remote);
if ($actual < 0 || $actual !== $expected) throw new RuntimeException('Размер не подтверждён');
echo "Размер переданных байтов совпал\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
Размер переданных байтов совпал

Нужна поддержка SIZE. Совпадение размера не является проверкой хеша; получатель ещё должен разобрать/принять файл. Загружайте уникальное имя партии, чтобы повтор не перезаписывал чужую выгрузку. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Рядом: ftp_fput, ftp_nb_put, ftp_rename.

ftp_fputПередать данные из уже открытого источника, не требуя имени постоянного файла.

PHP 4+ · FTP

ftp_fput(FTP\Connection $ftp, string $remote_filename, resource $stream, int $mode = FTP_BINARY, int $offset = 0): bool

Передать данные из уже открытого источника, не требуя имени постоянного файла.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
remote_filenameУдалённая цель.
streamЧитаемый локальный stream, чтение до EOF; после генерации нужен rewind.
offsetУдалённая стартовая позиция, связанная с AUTOSEEK локального источника.
Результатtrue/false; закрывать stream должен вызывающий код.
Как применяется ftp_fput
  1. Записали CSV в stream
  2. Вернули позицию на начало
  3. FPUT читает до EOF
  4. В finally закрыли stream
Сформировать CSV без отдельного постоянного файлаПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$stream = fopen('php://temp', 'w+b');
if ($stream === false) throw new RuntimeException('Нет stream');
try {
    fputcsv($stream, ['sku', 'qty'], ',', '"', '');
    fputcsv($stream, ['A42', 7], ',', '"', '');
    rewind($stream);
    if (!ftp_fput($ftp, 'outgoing/lesson-buffer.csv', $stream, FTP_BINARY)) throw new RuntimeException('Не передано');
    echo "CSV из буфера передан\n";
} finally { fclose($stream); }
} finally { ftp_close($ftp); }
Ожидаемый результат
CSV из буфера передан

После fputcsv указатель в конце; без rewind отправлять будет нечего. php://temp может уйти из памяти во временный файл после порога — это не обещание нулевого использования диска. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Отправить остаток stream от текущей позицииПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$stream = fopen('source.txt', 'rb');
if ($stream === false) throw new RuntimeException('Нет файла');
try {
    fgets($stream); // Skip the local service header.
    ftp_set_option($ftp, FTP_AUTOSEEK, false);
    if (!ftp_fput($ftp, 'outgoing/lesson-body.txt', $stream, FTP_BINARY)) throw new RuntimeException('Не передано');
    echo "Передано тело без локального заголовка\n";
} finally { fclose($stream); }
} finally { ftp_close($ftp); }
Ожидаемый результат
Передано тело без локального заголовка

source.txt содержит служебную первую строку и тело. Выключенное AUTOSEEK делает намерение явным: читать с текущего локального указателя, записывать удалённую цель с начала. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Рядом: ftp_put, ftp_fget, ftp_nb_fput.

ftp_appendДополнить конец удалённого файла, сохранив прежнее содержимое.

PHP 7.2+ · FTP

ftp_append(FTP\Connection $ftp, string $remote_filename, string $local_filename, int $mode = FTP_BINARY): bool

Дополнить конец удалённого файла, сохранив прежнее содержимое.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
remote/localУдалённый дополняемый файл и локальный источник всей добавки.
modeBINARY либо ASCII; аргумента resume здесь нет.
Результатbool; поддержка APPE и права определяются сервером.
Риск повторовПосле потери подтверждения нельзя считать повтор безопасным: добавка может уже существовать.
Как применяется ftp_append
  1. Локальная строка готова
  2. APPE выбирает конец цели
  3. Байты добавлены
  4. Повтор требует политики дедупликации
Добавить свою строку в учебный журналПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
if (!ftp_append($ftp, 'outgoing/lesson-events.log', 'event.txt', FTP_BINARY)) throw new RuntimeException('APPE отклонён');
echo "Строка добавлена\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
Строка добавлена

event.txt приложен; каждая запись уже заканчивается LF. append не вставляет разделитель сам. Сервер может создать отсутствующую цель по правилам APPE. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Добавить заранее собранную пачку строкПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$rows = ["B17 reserved 3", "A42 released 1"];
if (file_put_contents('batch.log', implode("\n", $rows) . "\n") === false) throw new RuntimeException('Нет локальной пачки');
if (!ftp_append($ftp, 'outgoing/lesson-events.log', 'batch.log', FTP_BINARY)) throw new RuntimeException('Пачка не добавлена');
echo "Пачка отправлена одним APPE\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
Пачка отправлена одним APPE

Повтор после неопределённого сетевого отказа может продублировать строки. Для событий с денежными/складскими последствиями нужен ID и дедупликация у получателя; сам append не идемпотентен. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Рядом: ftp_put, ftp_fput.

ftp_allocСогласовать предварительное место с сервером, который явно этого требует.

PHP 5+ · FTP

ftp_alloc(FTP\Connection $ftp, int $size, string &$response = null): bool

Согласовать предварительное место с сервером, который явно этого требует.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
sizeКоличество байтов, не килобайт и не длина имени.
responseНеобязательная переменная, заполняемая по ссылке текстом ответа.
Результатtrue/false; true может означать отсутствие необходимости резерва.
ОграничениеПоддержка ALLO необязательна; резерв не заменяет результат передачи.
Как применяется ftp_alloc
  1. Узнали размер локального файла
  2. ALLO отправляет число
  3. Получили bool и текст
  4. Решение продолжить зависит от договора
Запросить резерв и сохранить ответ сервераПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$response = '';
$ok = @ftp_alloc($ftp, 14, $response);
echo $ok ? "Сервер разрешил продолжить\n" : "ALLO не поддержан или отклонён\n";
} finally { ftp_close($ftp); }

Для стенда с ALLO ожидается первая строка; для обычного сервера, отклоняющего ALLO, вторая. Полный response можно сохранить в защищённой диагностике; он не является стабильным машинным форматом. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Использовать ALLO только по договору конкретного сервераПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$size = filesize('export.csv');
if ($size === false) throw new RuntimeException('Нет локального файла');
$response = '';
if (!ftp_alloc($ftp, $size, $response)) throw new RuntimeException('Этот стенд требует успешного ALLO');
if (!ftp_put($ftp, 'outgoing/lesson-allocated.csv', 'export.csv')) throw new RuntimeException('Передача не удалась');
echo "Обязательный ALLO и загрузка выполнены\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
Обязательный ALLO и загрузка выполнены

Контекст: свой сервер явно требует/реализует предварительное резервирование. У многих серверов ALLO не поддержан или true означает лишь «предварительный резерв не нужен». Не вводите его как обязательный шаг любого FTP. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Рядом: ftp_put, ftp_size.

ftp_nb_getСкачать файл порциями, сохранив управление между продолжениями.

PHP 4.3+ · FTP

ftp_nb_get(FTP\Connection $ftp, string $local_filename, string $remote_filename, int $mode = FTP_BINARY, int $offset = 0): int|false

Скачать файл порциями, сохранив управление между продолжениями.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
Локальная сторонаПуть локальной цели; может быть перезаписана.
Удалённая сторонаПуть источника.
mode/offsetКак у соответствующего синхронного get/put: BINARY default, resume с учётом AUTOSEEK.
РезультатFTP_FAILED / FTP_FINISHED / FTP_MOREDATA либо false при открытии локального файла.
ВерсииPHP 4.3; mode необязателен с 7.3; Connection с 8.1.
Как применяется ftp_nb_get
  1. Начальная функция запускает передачу
  2. Проверка FTP_MOREDATA
  3. Другой короткий полезный шаг
  4. continue продвигает ту же передачу
  5. Только FTP_FINISHED означает завершение
Завершить передачу через явные состоянияПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$state = ftp_nb_get($ftp, 'lesson-nb-copy.csv', 'incoming/stock.csv', FTP_BINARY);
while ($state === FTP_MOREDATA) {
    $state = ftp_nb_continue($ftp);
}
if ($state !== FTP_FINISHED) throw new RuntimeException('Передача не завершена');
echo file_get_contents('lesson-nb-copy.csv');
} finally { ftp_close($ftp); }
Ожидаемый результат
sku,qty
A42,7

Цикл продолжает ровно текущую операцию; FTP_MOREDATA не означает успех, FTP_FAILED не равен исключению. Пока transfer не завершён, не запускайте новую передачу на том же connection. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Ограничить общее ожидание между шагамиПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$deadline = hrtime(true) + 5_000_000_000;
$state = ftp_nb_get($ftp, 'lesson-nb-copy.csv', 'incoming/stock.csv', FTP_BINARY);
while ($state === FTP_MOREDATA) {
    if (hrtime(true) >= $deadline) throw new RuntimeException('Общий срок передачи истёк');
    $state = ftp_nb_continue($ftp);
}
if ($state !== FTP_FINISHED) throw new RuntimeException('Передача не завершена');
echo file_get_contents('lesson-nb-copy.csv');
} finally { ftp_close($ftp); }
Ожидаемый результат
sku,qty
A42,7

hrtime задаёт общий срок, который проверяется между вызовами continue. Сам continue способен ждать сетевой timeout: это не жёсткое прерывание ровно на пятой секунде. Для полного контроля длительности используют отдельный worker/клиент с соответствующим договором. При отказе finally закрывает connection; файл может остаться частичным. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

«Non-blocking» здесь означает возможность выполнять свой код между шагами; фонового потока PHP не создаётся. Не блокируйте worker долгими посторонними действиями внутри цикла. Статус проверяют строго через ===/!==, а не if($state), поскольку целые константы обозначают три различных состояния. Если локальный файл не удалось открыть, этот вариант дополнительно возвращает bool false, в отличие от stream-варианта.

Рядом: ftp_nb_continue, ftp_get.

ftp_nb_fgetСкачать файл порциями, сохранив управление между продолжениями.

PHP 4.3+ · FTP

ftp_nb_fget(FTP\Connection $ftp, resource $stream, string $remote_filename, int $mode = FTP_BINARY, int $offset = 0): int

Скачать файл порциями, сохранив управление между продолжениями.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
Локальная сторонаПереданный записываемый stream.
Удалённая сторонаПуть источника.
mode/offsetКак у соответствующего синхронного get/put: BINARY default, resume с учётом AUTOSEEK.
РезультатFTP_FAILED / FTP_FINISHED / FTP_MOREDATA.
ВерсииPHP 4.3; mode необязателен с 7.3; Connection с 8.1.
Как применяется ftp_nb_fget
  1. Начальная функция запускает передачу
  2. Проверка FTP_MOREDATA
  3. Другой короткий полезный шаг
  4. continue продвигает ту же передачу
  5. Только FTP_FINISHED означает завершение
Завершить передачу через явные состоянияПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$stream = fopen('php://temp', 'w+b');
if ($stream === false) throw new RuntimeException('Нет stream');
try {
$state = ftp_nb_fget($ftp, $stream, 'incoming/stock.csv', FTP_BINARY);
while ($state === FTP_MOREDATA) {
    $state = ftp_nb_continue($ftp);
}
if ($state !== FTP_FINISHED) throw new RuntimeException('Передача не завершена');
rewind($stream);
echo stream_get_contents($stream);
} finally { fclose($stream); }
} finally { ftp_close($ftp); }
Ожидаемый результат
sku,qty
A42,7

Цикл продолжает ровно текущую операцию; FTP_MOREDATA не означает успех, FTP_FAILED не равен исключению. Пока transfer не завершён, не запускайте новую передачу на том же connection. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Ограничить общее ожидание между шагамиПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$stream = fopen('php://temp', 'w+b');
if ($stream === false) throw new RuntimeException('Нет stream');
try {
$deadline = hrtime(true) + 5_000_000_000;
$state = ftp_nb_fget($ftp, $stream, 'incoming/stock.csv', FTP_BINARY);
while ($state === FTP_MOREDATA) {
    if (hrtime(true) >= $deadline) throw new RuntimeException('Общий срок передачи истёк');
    $state = ftp_nb_continue($ftp);
}
if ($state !== FTP_FINISHED) throw new RuntimeException('Передача не завершена');
rewind($stream);
echo stream_get_contents($stream);
} finally { fclose($stream); }
} finally { ftp_close($ftp); }
Ожидаемый результат
sku,qty
A42,7

hrtime задаёт общий срок, который проверяется между вызовами continue. Сам continue способен ждать сетевой timeout: это не жёсткое прерывание ровно на пятой секунде. Для полного контроля длительности используют отдельный worker/клиент с соответствующим договором. При отказе finally закрывает connection; файл может остаться частичным. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

«Non-blocking» здесь означает возможность выполнять свой код между шагами; фонового потока PHP не создаётся. Не блокируйте worker долгими посторонними действиями внутри цикла. Статус проверяют строго через ===/!==, а не if($state), поскольку целые константы обозначают три различных состояния. Stream должен оставаться открытым до FTP_FINISHED; его затем закрывает владелец.

Рядом: ftp_nb_continue, ftp_fget.

ftp_nb_putЗагрузить файл порциями, сохранив управление между продолжениями.

PHP 4.3+ · FTP

ftp_nb_put(FTP\Connection $ftp, string $remote_filename, string $local_filename, int $mode = FTP_BINARY, int $offset = 0): int|false

Загрузить файл порциями, сохранив управление между продолжениями.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
Локальная сторонаПуть существующего локального источника.
Удалённая сторонаПуть цели.
mode/offsetКак у соответствующего синхронного get/put: BINARY default, resume с учётом AUTOSEEK.
РезультатFTP_FAILED / FTP_FINISHED / FTP_MOREDATA либо false при открытии локального файла.
ВерсииPHP 4.3; mode необязателен с 7.3; Connection с 8.1.
Как применяется ftp_nb_put
  1. Начальная функция запускает передачу
  2. Проверка FTP_MOREDATA
  3. Другой короткий полезный шаг
  4. continue продвигает ту же передачу
  5. Только FTP_FINISHED означает завершение
Завершить передачу через явные состоянияПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$state = ftp_nb_put($ftp, 'outgoing/lesson-ftp_nb_put.csv', 'export.csv', FTP_BINARY);
while ($state === FTP_MOREDATA) {
    $state = ftp_nb_continue($ftp);
}
if ($state !== FTP_FINISHED) throw new RuntimeException('Передача не завершена');
echo "Пачка передана\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
Пачка передана

Цикл продолжает ровно текущую операцию; FTP_MOREDATA не означает успех, FTP_FAILED не равен исключению. Пока transfer не завершён, не запускайте новую передачу на том же connection. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Ограничить общее ожидание между шагамиПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$deadline = hrtime(true) + 5_000_000_000;
$state = ftp_nb_put($ftp, 'outgoing/lesson-ftp_nb_put.csv', 'export.csv', FTP_BINARY);
while ($state === FTP_MOREDATA) {
    if (hrtime(true) >= $deadline) throw new RuntimeException('Общий срок передачи истёк');
    $state = ftp_nb_continue($ftp);
}
if ($state !== FTP_FINISHED) throw new RuntimeException('Передача не завершена');
echo "Пачка передана\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
Пачка передана

hrtime задаёт общий срок, который проверяется между вызовами continue. Сам continue способен ждать сетевой timeout: это не жёсткое прерывание ровно на пятой секунде. Для полного контроля длительности используют отдельный worker/клиент с соответствующим договором. При отказе finally закрывает connection; файл может остаться частичным. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

«Non-blocking» здесь означает возможность выполнять свой код между шагами; фонового потока PHP не создаётся. Не блокируйте worker долгими посторонними действиями внутри цикла. Статус проверяют строго через ===/!==, а не if($state), поскольку целые константы обозначают три различных состояния. Если локальный файл не удалось открыть, этот вариант дополнительно возвращает bool false, в отличие от stream-варианта.

Рядом: ftp_nb_continue, ftp_put.

ftp_nb_fputЗагрузить файл порциями, сохранив управление между продолжениями.

PHP 4.3+ · FTP

ftp_nb_fput(FTP\Connection $ftp, string $remote_filename, resource $stream, int $mode = FTP_BINARY, int $offset = 0): int

Загрузить файл порциями, сохранив управление между продолжениями.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
Локальная сторонаПереданный читаемый stream.
Удалённая сторонаПуть цели.
mode/offsetКак у соответствующего синхронного get/put: BINARY default, resume с учётом AUTOSEEK.
РезультатFTP_FAILED / FTP_FINISHED / FTP_MOREDATA.
ВерсииPHP 4.3; mode необязателен с 7.3; Connection с 8.1.
Как применяется ftp_nb_fput
  1. Начальная функция запускает передачу
  2. Проверка FTP_MOREDATA
  3. Другой короткий полезный шаг
  4. continue продвигает ту же передачу
  5. Только FTP_FINISHED означает завершение
Завершить передачу через явные состоянияПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$stream = fopen('php://temp', 'w+b');
if ($stream === false) throw new RuntimeException('Нет stream');
fwrite($stream, "sku,qty\nA42,7\n"); rewind($stream);
try {
$state = ftp_nb_fput($ftp, 'outgoing/lesson-ftp_nb_fput.csv', $stream, FTP_BINARY);
while ($state === FTP_MOREDATA) {
    $state = ftp_nb_continue($ftp);
}
if ($state !== FTP_FINISHED) throw new RuntimeException('Передача не завершена');
echo "Пачка передана\n";
} finally { fclose($stream); }
} finally { ftp_close($ftp); }
Ожидаемый результат
Пачка передана

Цикл продолжает ровно текущую операцию; FTP_MOREDATA не означает успех, FTP_FAILED не равен исключению. Пока transfer не завершён, не запускайте новую передачу на том же connection. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Ограничить общее ожидание между шагамиПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$stream = fopen('php://temp', 'w+b');
if ($stream === false) throw new RuntimeException('Нет stream');
fwrite($stream, "sku,qty\nA42,7\n"); rewind($stream);
try {
$deadline = hrtime(true) + 5_000_000_000;
$state = ftp_nb_fput($ftp, 'outgoing/lesson-ftp_nb_fput.csv', $stream, FTP_BINARY);
while ($state === FTP_MOREDATA) {
    if (hrtime(true) >= $deadline) throw new RuntimeException('Общий срок передачи истёк');
    $state = ftp_nb_continue($ftp);
}
if ($state !== FTP_FINISHED) throw new RuntimeException('Передача не завершена');
echo "Пачка передана\n";
} finally { fclose($stream); }
} finally { ftp_close($ftp); }
Ожидаемый результат
Пачка передана

hrtime задаёт общий срок, который проверяется между вызовами continue. Сам continue способен ждать сетевой timeout: это не жёсткое прерывание ровно на пятой секунде. Для полного контроля длительности используют отдельный worker/клиент с соответствующим договором. При отказе finally закрывает connection; файл может остаться частичным. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

«Non-blocking» здесь означает возможность выполнять свой код между шагами; фонового потока PHP не создаётся. Не блокируйте worker долгими посторонними действиями внутри цикла. Статус проверяют строго через ===/!==, а не if($state), поскольку целые константы обозначают три различных состояния. Stream должен оставаться открытым до FTP_FINISHED; его затем закрывает владелец.

Рядом: ftp_nb_continue, ftp_fput.

ftp_nb_continueПродвинуть уже запущенную передачу в этом соединении.

PHP 4.3+ · FTP

ftp_nb_continue(FTP\Connection $ftp): int

Продвинуть уже запущенную передачу в этом соединении.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
ftpИменно connection с текущей ftp_nb_* передачей.
РезультатFTP_FAILED, FTP_FINISHED или FTP_MOREDATA. Без активной операции — отказ, а не запуск новой.
ОграничениеОдин активный transfer на connection; не закрывайте используемый stream до завершения.
Как применяется ftp_nb_continue
  1. nb_* вернул MOREDATA
  2. continue делает следующий шаг
  3. Цикл проверяет статус
  4. FINISHED или FAILED завершает цикл
Продолжать запущенное скачивание, не начинать его зановоПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$state = ftp_nb_get($ftp, 'lesson-continue.csv', 'incoming/stock.csv');
while ($state === FTP_MOREDATA) {
    $state = ftp_nb_continue($ftp);
}
if ($state !== FTP_FINISHED) throw new RuntimeException('Не закончено');
echo file_get_contents('lesson-continue.csv');
} finally { ftp_close($ftp); }
Ожидаемый результат
sku,qty
A42,7

Начальную ftp_nb_get вызывают один раз; повтор внутри цикла переоткрывал бы операцию. Количество шагов зависит от размера/сети и не должно использоваться как процент готовности. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Продолжать загрузку из stream, сохраняя его открытымПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$stream = fopen('export.csv', 'rb');
if ($stream === false) throw new RuntimeException('Нет экспорта');
try {
    $state = ftp_nb_fput($ftp, 'outgoing/lesson-continue.csv', $stream);
    while ($state === FTP_MOREDATA) {
        $state = ftp_nb_continue($ftp);
    }
    if ($state !== FTP_FINISHED) throw new RuntimeException('Не отправлено');
    echo "Передача stream завершена\n";
} finally { fclose($stream); }
} finally { ftp_close($ftp); }
Ожидаемый результат
Передача stream завершена

При необходимости процент считают по объёму уже обработанного источника и отдельно завершающему подтверждению; позиция stream не доказывает принятие файла получателем. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Рядом: ftp_nb_get, ftp_nb_put, ftp_nb_fget, ftp_nb_fput.

ftp_nlistПолучить простой список удалённых имён для следующего шага обработки.

PHP 4+ · FTP

ftp_nlist(FTP\Connection $ftp, string $directory): array|false

Получить простой список удалённых имён для следующего шага обработки.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
directoryПуть каталога, иногда серверные опции.
РезультатМассив строк имён либо false. Метаданных размера/типа здесь нет.
ЦенаОтдельное соединение данных, весь список находится в памяти.
Как применяется ftp_nlist
  1. NLST выбирает каталог
  2. Сервер передаёт строки
  3. PHP собирает массив
  4. Приложение отбирает нужные имена
Получить имена в входящей папкеПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$names = ftp_nlist($ftp, 'incoming');
if ($names === false) throw new RuntimeException('NLST не выполнен');
echo is_array($names) ? "Получен список имён\n" : "Неверный тип\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
Получен список имён

Пустой массив — список без элементов, а не обязательно ошибка. Формат относительных/полных имён зависит от сервера; сначала посмотрите реальные значения на своём стенде. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Выбрать имена CSV, не предполагая тип каждого элементаПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$names = ftp_nlist($ftp, 'incoming');
if ($names === false) throw new RuntimeException('Нет списка');
foreach ($names as $name) {
    if (str_ends_with(strtolower($name), '.csv')) echo basename($name), "\n";
}
} finally { ftp_close($ftp); }
Ожидаемый результат
stock.csv

Ожидается учебная папка с единственным CSV. Расширение в имени не доказывает ни файловый тип, ни содержимое; для типа dir/file используйте MLSD, для данных — последующую проверку. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

directory передаётся серверу и может включать LIST/NLST опции; универсального shell-экранирования здесь нет. Пробелы и имена, начинающиеся с -, требуют проверки договора конкретного сервера. Не добавляйте -la к произвольному пользовательскому тексту. Большой каталог возвращается целиком массивом: это затраты памяти и передачи данных, пагинации в функции нет.

Рядом: ftp_mlsd, ftp_rawlist.

ftp_rawlistПолучить подробные строки LIST без обещания единого формата полей.

PHP 4+ · FTP

ftp_rawlist(FTP\Connection $ftp, string $directory, bool $recursive = false): array|false

Получить подробные строки LIST без обещания единого формата полей.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
directoryПуть и, если нужно, поддержанные сервером аргументы LIST.
recursivetrue добавляет -R; сервер должен это понимать.
РезультатМассив необработанных строк либо false.
ПрименениеДиагностика/адаптер к известному серверу; для общего машинного формата предпочтительнее MLSD.
Как применяется ftp_rawlist
  1. Команда LIST
  2. Сервер формирует строки
  3. PHP их не разбирает
  4. Человек читает либо ваш ограниченный адаптер обрабатывает
Посмотреть серверное представление каталогаПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$lines = ftp_rawlist($ftp, 'incoming');
if ($lines === false) throw new RuntimeException('LIST не выполнен');
foreach ($lines as $line) echo $line, "\n";
} finally { ftp_close($ftp); }

Вывод — строки LIST вашего сервера: Unix ls-подобный либо иной формат. Точные права/дата/владелец меняются, поэтому здесь не заявляется универсальный stdout. В HTML выводите строки через htmlspecialchars. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Сохранить диагностический листинг без хрупкого разбора имениПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$lines = ftp_rawlist($ftp, 'incoming', false);
if ($lines === false) throw new RuntimeException('Нет листинга');
if (file_put_contents('lesson-listing.txt', implode("\n", $lines) . "\n") === false) throw new RuntimeException('Нет локального журнала');
echo "Листинг сохранён для диагностики\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
Листинг сохранён для диагностики

Не используйте explode(" ")[8] как переносимый парсер: повторные пробелы, имена с пробелами, symlink и Windows LIST нарушают предположение. Журнал храните вне публичной папки. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Рядом: ftp_mlsd, ftp_nlist, ftp_systype.

ftp_mlsdПолучить структурированные метаданные без разбора произвольного вывода LIST.

PHP 7.2+ · FTP

ftp_mlsd(FTP\Connection $ftp, string $directory): array|false

Получить структурированные метаданные без разбора произвольного вывода LIST.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
directoryУдалённый каталог; нужна поддержка команды MLSD.
РезультатСписок массивов с name и предоставленными facts; false при отказе.
ВерсииPHP 7.2; Connection с 8.1.
ПроверкиПроверяйте существование и тип каждого нужного fact.
Как применяется ftp_mlsd
  1. MLSD incoming
  2. Запись name=stock.csv, type=file, size=14
  3. Проверяем поля
  4. Берём файл по явному правилу
Выбрать только обычные файлы из структурированного спискаПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$entries = ftp_mlsd($ftp, 'incoming');
if ($entries === false) throw new RuntimeException('Сервер не вернул MLSD');
foreach ($entries as $entry) {
    if (($entry['type'] ?? null) === 'file') echo $entry['name'], "\n";
}
} finally { ftp_close($ftp); }
Ожидаемый результат
stock.csv

На учебном стенде incoming содержит один файл. type может также обозначать dir, cdir, pdir либо расширение; не считайте всё не-dir обычным файлом. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Отобрать CSV и проверить текстовый размер перед преобразованиемПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$entries = ftp_mlsd($ftp, 'incoming');
if ($entries === false) throw new RuntimeException('Нет MLSD');
foreach ($entries as $entry) {
    if (($entry['type'] ?? '') !== 'file' || !str_ends_with($entry['name'] ?? '', '.csv')) continue;
    $size = $entry['size'] ?? null;
    if (!is_string($size) || !ctype_digit($size)) throw new RuntimeException('Нет корректного SIZE fact');
    // This import accepts at most six decimal digits and then a smaller limit.
    if (strlen($size) > 6 || (int)$size > 100_000) throw new RuntimeException('Выгрузка слишком велика');
    echo $entry['name'], ': ', (int)$size, " байт\n";
}
} finally { ftp_close($ftp); }
Ожидаемый результат
stock.csv: 14 байт

Facts приходят строками и не обязаны присутствовать все. Ограничение до int-приведения не даёт огромной десятичной строке переполнить прикладной диапазон. Этот фильтр не заменяет ограничение реально скачанного размера и проверку CSV. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Часто встречаемое полеЧто учитывать
nameИмя записи; пробелы принадлежат имени, не разделяют поля. Не превращайте его напрямую в локальный путь.
typefile/dir/cdir/pdir и возможные дополнения сервера.
sizeЧисловая строка; отсутствие не означает ноль.
modifyМетка UTC формата MLSx, возможна дробная часть; не строка локального date().
perm / unique / UNIX.*Возможности/идентификатор и расширенные facts; конкретный набор объявляет сервер.

MLSD предназначен для машинной обработки, но остаётся сетевым снимком: после получения файла могли изменить или удалить. При очень большом каталоге весь массив также занимает память. По возможности договаривайтесь о каталогах партий и финальных именах, а не перечитывайте миллионы записей.

Рядом: ftp_nlist, ftp_rawlist, ftp_size.

ftp_systypeПрочитать серверный системный идентификатор для диагностики совместимости.

PHP 4+ · FTP

ftp_systype(FTP\Connection $ftp): string|false

Прочитать серверный системный идентификатор для диагностики совместимости.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
РезультатСтрока системного типа или false.
ГраницаОтвет сервера не доказывает реальную ОС/версию и не заменяет MLSD/FEAT.
Как применяется ftp_systype
  1. SYST запрашивает идентификатор
  2. Сервер отвечает строкой
  3. Выбираем известный договор
  4. Не делаем выводов о правах/защите
Прочитать ответ о системном типеПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$system = ftp_systype($ftp);
if ($system === false) throw new RuntimeException('SYST не поддержан');
echo $system, "\n";
} finally { ftp_close($ftp); }

Типичный ответ UNIX, но значение задаёт сервер. Точный stdout зависит от стенда. Это не надёжный способ определить ОС физического хоста: сервер может эмулировать иной формат. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Выбрать заранее реализованный адаптер известного сервераПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$system = ftp_systype($ftp);
if ($system === false) throw new RuntimeException('Нет системного идентификатора');
if (str_starts_with(strtoupper($system), 'UNIX')) {
    echo "Включён известный UNIX LIST адаптер\n";
} else {
    echo "Нужен другой адаптер или MLSD\n";
}
} finally { ftp_close($ftp); }

Ожидается одна из двух подписанных ветвей по ответу стенда. SYST — только один признак: формат LIST отдельно фиксируют примерами и проверяют, иначе ложное предположение испортит имена файлов. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Рядом: ftp_rawlist, ftp_mlsd, ftp_raw.

ftp_sizeПолучить предварительный размер и отличить пустой файл от ошибки.

PHP 4+ · FTP

ftp_size(FTP\Connection $ftp, string $filename): int

Получить предварительный размер и отличить пустой файл от ошибки.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
filenameУдалённый файл.
РезультатБайты, включая 0; -1 при отказе/отсутствии поддержки.
ГраницаНе все серверы реализуют SIZE; значение относится к моменту запроса.
Как применяется ftp_size
  1. SIZE stock.csv
  2. Получили 14
  3. Проверили диапазон
  4. Решили скачивать с собственным лимитом
Узнать размер файла в байтахПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$bytes = ftp_size($ftp, 'incoming/stock.csv');
if ($bytes === -1) throw new RuntimeException('SIZE не получен');
echo $bytes, " байт\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
14 байт

Нужен учебный файл из 14 ASCII/LF байтов. Ноль — допустимый размер пустого файла, отказ — именно -1; проверка if(!$bytes) смешала бы эти ситуации. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Отказаться от заведомо слишком большой выгрузкиПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$bytes = ftp_size($ftp, 'incoming/stock.csv');
if ($bytes < 0) throw new RuntimeException('Размер неизвестен: выберите явную политику');
if ($bytes > 100_000) throw new RuntimeException('Превышен лимит импорта');
echo "Предварительный лимит размера пройден\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
Предварительный лимит размера пройден

SIZE может быть не поддержан. Файл способен измениться после проверки, поэтому во время/после загрузки также контролируйте фактический объём. Размер не подтверждает содержимое или контрольную сумму. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Рядом: ftp_mdtm, ftp_mlsd, ftp_get.

ftp_mdtmПолучить время изменения файла для отображения и предварительного сравнения версии.

PHP 4+ · FTP

ftp_mdtm(FTP\Connection $ftp, string $filename): int

Получить время изменения файла для отображения и предварительного сравнения версии.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
filenameУдалённый файл; для каталогов функция не предназначена.
РезультатUnix timestamp либо -1; поддержка MDTM необязательна.
ПредставлениеВыбирайте явную timezone при форматировании; не прибавляйте смещение к timestamp вручную.
Как применяется ftp_mdtm
  1. MDTM спрашивает метку
  2. PHP преобразует её в timestamp
  3. gmdate выводит UTC
  4. Для версии нужны дополнительные гарантии
Показать момент изменения в явной зоне UTCПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$timestamp = ftp_mdtm($ftp, 'incoming/stock.csv');
if ($timestamp === -1) throw new RuntimeException('MDTM не получен');
echo gmdate('Y-m-d H:i:s', $timestamp), " UTC\n";
} finally { ftp_close($ftp); }

Вывод зависит от даты файла на стенде. Unix timestamp — число секунд момента времени, собственной локальной зоны у него нет; gmdate форматирует UTC, date использует текущую зону PHP. Стандартный MDTM приходит в UTC. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Сравнить два наблюдения, не выдавая их за транзакциюПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$before = ftp_mdtm($ftp, 'incoming/stock.csv');
if ($before === -1) throw new RuntimeException('Нет исходной метки');
if (!ftp_get($ftp, 'lesson-mtime.csv', 'incoming/stock.csv')) throw new RuntimeException('Не скачано');
$after = ftp_mdtm($ftp, 'incoming/stock.csv');
echo $after === $before ? "Метка времени не изменилась\n" : "Нужно повторно проверить версию\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
Метка времени не изменилась

Для неподвижного учебного файла ожидается первая строка. Равенство mtime не доказывает идентичность: точность времени ограничена, сервер может сохранить старую метку. Для строгой согласованности используйте финальный immutable файл и хеш/манифест от поставщика. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Рядом: ftp_size, ftp_mlsd, ftp_get.

ftp_rawПолучить необработанные строки ответа на известную FTP команду.

PHP 5+ · FTP

ftp_raw(FTP\Connection $ftp, string $command): ?array

Получить необработанные строки ответа на известную FTP команду.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
commandОдна доверенная команда управляющего канала.
РезультатМассив строк ответа или null; ответа false по сигнатуре нет.
УспехФункция не решает, успешен ли серверный код. Проверка лежит на приложении.
Как применяется ftp_raw
  1. Отправили NOOP
  2. Получили строку 200 ...
  3. Проверили именно код
  4. Не приняли массив с 500 за успех
Посмотреть объявленные возможности без изменения файловПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$lines = ftp_raw($ftp, 'FEAT');
if ($lines === null) throw new RuntimeException('Ответ не получен');
foreach ($lines as $line) echo $line, "\n";
} finally { ftp_close($ftp); }

Вывод зависит от FTP сервера: FEAT обычно многострочный. Наличие массива не означает успех команды; сервер может вернуть строку 500/502. Не записывайте пароли/секретные команды в общий журнал. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Проверить код завершения известной командыПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$lines = ftp_raw($ftp, 'NOOP');
if ($lines === null || $lines === []) throw new RuntimeException('Нет ответа');
$last = $lines[array_key_last($lines)];
echo str_starts_with($last, '200 ') ? "NOOP принят\n" : "Нужен разбор отказа сервера\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
NOOP принят

Предусловие: сервер поддерживает стандартный NOOP. Для произвольных команд нужен разбор их допустимых кодов и многострочных ответов; этот тест не универсальный parser всего FTP. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Не передавайте через raw произвольную команду пользователя. RETR/STOR/LIST работают ещё и с data channel; отправка одной текстовой команды не заменяет ftp_get/put/list. Самостоятельные CWD/TYPE/PASV могут рассогласовать настройки, которые хранит расширение. Используйте профильные функции, а raw оставьте диагностике и явно описанным расширениям сервера.

Рядом: ftp_site, ftp_systype.

ftp_siteОбратиться к специальной команде конкретного FTP сервера по документированному договору.

PHP 4+ · FTP

ftp_site(FTP\Connection $ftp, string $command): bool

Обратиться к специальной команде конкретного FTP сервера по документированному договору.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
commandТекст после SITE, например HELP; набор не стандартизован одинаково для всех серверов.
Результатtrue/false; не вывод команды.
ГраницаПрава, группы и иные операции зависят от server. Не применять чужие SITE примеры без его документации.
Как применяется ftp_site
  1. Известна поддержанная SITE команда
  2. Передали только её фиксированный текст
  3. Сервер проверил полномочия
  4. Приложение проверило bool
Спросить о специальных командах учебного сервераПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$ok = ftp_site($ftp, 'HELP');
echo $ok ? "SITE HELP принят\n" : "SITE HELP не поддержан\n";
} finally { ftp_close($ftp); }

Это пример для сервера с SITE HELP; вывод зависит от реализации. Возвращается bool, а не текст справки. Если нужны сами строки, применяют ftp_raw($ftp, "SITE HELP"). Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Выполнить заранее оговорённую SITE операциюПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
if (!ftp_site($ftp, 'CHMOD 600 outgoing/lesson-private.txt')) throw new RuntimeException('SITE CHMOD не принят');
echo "Команда прав принята\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
Команда прав принята

Нужен свой заранее созданный файл и сервер с SITE CHMOD. Для этой задачи проще ftp_chmod с отдельными параметрами; строка здесь показывает протокол. Пробелы/спецсимволы в именах подчиняются именно серверному parser, не shell escaping PHP. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Рядом: ftp_raw, ftp_chmod.

ftp_execРазличать редкое серверное расширение SITE EXEC и запуск программы на своей PHP машине.

PHP 4.0.3+ · FTP

ftp_exec(FTP\Connection $ftp, string $command): bool

Различать редкое серверное расширение SITE EXEC и запуск программы на своей PHP машине.

FTP\Connection — состояние одного соединения с файловым сервером. В ftp_get($ftp, "copy.csv", "incoming/stock.csv", FTP_BINARY) скобки содержат аргументы: соединение, локальную цель, удалённый источник и режим. Результат проверяют до чтения файла. «Удалённый» путь относится к FTP учётной записи, «локальный» — к машине, где исполняется PHP; браузер пользователя здесь не участвует.

Начало и файлы окружения: две стороны, два канала и учебная учётная запись. Вызов функции, работа с локальным файлом, ошибки и finally. С PHP 8.1 соединение является объектом, старое is_resource для него не подходит.

Часть договораСмысл и условия
commandТекст команды для заранее известного серверного SITE EXEC.
Результатtrue, если сервер ответил 200, иначе false. Вывод программы не возвращается.
ПрименимостьТолько специально настроенный доверенный сервер и ограниченная команда.
Как применяется ftp_exec
  1. Приложение выбрало разрешённое действие
  2. FTP послал SITE EXEC
  3. Сервер решил, выполнять ли его
  4. PHP получил bool, не stdout
Запросить только известную команду своего учебного FTP сервераПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$ok = ftp_exec($ftp, 'lesson-status');
echo $ok ? "Сервер принял SITE EXEC\n" : "SITE EXEC не поддержан или запрещён\n";
} finally { ftp_close($ftp); }

lesson-status — условное имя, которое заранее реализовал администратор собственного стенда; это не встроенная FTP/PHP команда. На обычном сервере ожидается отказ. Ничего из HTTP ввода не конкатенируется в command. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

Сопоставить действие приложения с фиксированной серверной командойПример для указанного окружения
<?php
declare(strict_types=1);

require __DIR__ . '/ftp-lab.php';
$ftp = openLessonFtp();
try {
$commands = ['status' => 'lesson-status'];
$action = 'status';
if (!array_key_exists($action, $commands)) throw new RuntimeException('Действие запрещено');
if (!ftp_exec($ftp, $commands[$action])) throw new RuntimeException('Сервер не выполнил договорённую команду');
echo "Оговорённое действие принято сервером\n";
} finally { ftp_close($ftp); }
Ожидаемый результат
Оговорённое действие принято сервером

Контекст: свой сервер явно предоставляет SITE EXEC lesson-status и возвращает 200. Allowlist не делает опасную команду безопасной сам по себе; команда должна иметь узкие полномочия. Для запуска Python/Node на PHP машине используется иной API exec/proc_open. Это пример для настроенного учебного FTP сервера: здесь проверен синтаксис, успешная серверная операция не заявляется. Условия и файлы перечислены в начале главы; не запускайте на чужом или рабочем каталоге.

ftp_exec отправляет SITE EXEC удалённому FTP серверу. Оно не запускает локальную оболочку PHP хоста и не возвращает stdout процесса: true означает серверный код 200. Большинство серверов эту возможность отключает. Не включайте удалённую оболочку ради обычной передачи файлов; отдельный узкий job API обычно проще контролировать.

Рядом: ftp_site, ftp_raw.

Источники и обсуждения

Код и руководство с собой

Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.

Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.

Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.