ftp_nb_continue()
Функция ftp_nb_continue() — встроенная функция PHP для продолжения асинхронной FTP-операции. Принимает один параметр.
Что такое ftp_nb_continue()?
ftp_nb_continue() — встроенная функция PHP, которая возобновляет — или продолжает — неблокирующую передачу файлов по FTP, начатую ранее. Аббревиатура nb в названии расшифровывается как non-blocking (неблокирующий): вместо того чтобы останавливать выполнение скрипта до завершения загрузки или скачивания всего файла, неблокирующие FTP-функции возвращают управление после каждого фрагмента, позволяя скрипту выполнять другие задачи в промежутках.
На этой странице описано, что возвращает функция, как работает цикл неблокирующей передачи, как обрабатывать ошибки и какие существуют типичные ловушки.
Как работают неблокирующие передачи
Обычная передача, например ftp_get(), является блокирующей: PHP ожидает полной загрузки файла перед переходом к следующей строке. Семейство неблокирующих функций — ftp_nb_get(), ftp_nb_put(), ftp_nb_fget() и ftp_nb_fput() — начинает передачу и сразу возвращает управление. Затем вы вызываете ftp_nb_continue() многократно, продвигая передачу на один фрагмент за раз, пока функция не сообщит о завершении.
Функция возвращает одну из трёх констант:
| Константа | Значение |
|---|---|
FTP_MOREDATA | Передача ещё продолжается — вызовите ftp_nb_continue() снова. |
FTP_FINISHED | Передача успешно завершена — остановите цикл. |
FTP_FAILED | Передача завершилась с ошибкой — обработайте ошибку и остановитесь. |
Примечание: стартовая функция (
ftp_nb_get()и т. д.) возвращает тот же набор констант, поэтому логика вашего цикла должна учитывать возможность завершения передачи уже при первом вызове.
Синтаксис ftp_nb_continue()
ftp_nb_continue(resource $ftp): intФункция принимает единственный параметр — $ftp: идентификатор соединения, возвращённый функцией ftp_connect() или ftp_ssl_connect().
PHP 8.1+: соединение теперь представлено объектом
FTP\Connectionвместоresource, однако ваш код изменять не нужно — вы по-прежнему передаёте значение, полученное отftp_connect().
Использование ftp_nb_continue()
Сначала запустите неблокирующую передачу, затем доведите её до завершения с помощью цикла:
<?php
// Open the connection and log in
$ftp = ftp_connect('ftp.example.com');
ftp_login($ftp, 'username', 'password');
ftp_pasv($ftp, true); // passive mode is usually required behind firewalls
// Start a non-blocking download: local_file <- remote_file
$state = ftp_nb_get($ftp, 'local_file.txt', 'remote_file.txt', FTP_BINARY);
// Drive the transfer forward until it finishes or fails
while ($state === FTP_MOREDATA) {
// You can do other work here while the file streams in
$state = ftp_nb_continue($ftp);
}
if ($state === FTP_FINISHED) {
echo "Download complete.\n";
} else {
echo "Download failed.\n";
}
ftp_close($ftp);Обратите внимание на порядок аргументов ftp_nb_get(): это (соединение, локальный_файл, удалённый_файл, режим) — локальный путь назначения указывается перед удалённым источником.
Обработка ошибок
Всегда проверяйте возвращаемое значение на каждой итерации. Если ftp_nb_continue() возвращает FTP_FAILED, передача прервалась — следует остановиться и сообщить об ошибке, а не зациклиться бесконечно:
<?php
$state = ftp_nb_get($ftp, 'local_file.txt', 'remote_file.txt', FTP_BINARY);
while ($state === FTP_MOREDATA) {
$state = ftp_nb_continue($ftp);
}
switch ($state) {
case FTP_FINISHED:
echo "Transfer succeeded.\n";
break;
case FTP_FAILED:
echo "Transfer failed.\n";
break;
}Поскольку условие цикла — === FTP_MOREDATA, цикл автоматически завершается как при FTP_FINISHED, так и при FTP_FAILED — последующий switch сообщает, что именно произошло.
Типичные ловушки
- Отсутствие проверки возвращаемого значения стартовой функции. Небольшой файл может полностью загрузиться во время выполнения
ftp_nb_get(), вернувFTP_FINISHEDещё до запуска цикла. Присвоение возвращаемого значения переменной$state(как показано выше) корректно обрабатывает этот случай. - Вызов
ftp_nb_continue()без активной передачи. Функция работает только тогда, когда неблокирующая операция находится в процессе выполнения; в противном случае она возвращаетFTP_FAILED. - Пустой «жёсткий» цикл. Весь смысл неблокирующего FTP — выполнять полезную работу между вызовами. Пустой цикл
whileпросто бесполезно занимает процессор и не даёт никакого преимущества перед блокирующимftp_get(). - Пассивный режим. За брандмауэром или NAT обычно необходимо вызвать
ftp_pasv()с параметромtrueдо начала передачи.
Заключение
ftp_nb_continue() возобновляет неблокирующую FTP-передачу, начатую функциями ftp_nb_get(), ftp_nb_put(), ftp_nb_fget() или ftp_nb_fput(). Вызывайте её в цикле, пока она возвращает FTP_MOREDATA, останавливайтесь при FTP_FINISHED и обрабатывайте FTP_FAILED — тогда ваш скрипт останется отзывчивым, пока файлы передаются в фоновом режиме.