W3docs

ftp_fget()

Функция ftp_fget() в PHP загружает файл с FTP-сервера и записывает его в уже открытый локальный файловый дескриптор.

Что такое ftp_fget()?

ftp_fget() загружает файл с FTP-сервера и записывает его в уже открытый локальный файловый дескриптор. В этом заключается ключевое отличие от ftp_get(): ftp_get() принимает локальный путь и самостоятельно создаёт файл, тогда как ftp_fget() принимает открытый файловый ресурс (значение, возвращаемое fopen()). Поскольку вы управляете дескриптором, ftp_fget() удобна, когда нужно записывать в поток, не являющийся обычным файлом, — временный поток (php://temp), буфер в памяти или дескриптор, позиционированный с помощью fseek().

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

Процедурное расширение FTP по-прежнему входит в состав PHP. Начиная с PHP 8.1 соединение представлено объектом FTP\Connection, а не resource, однако код остаётся неизменным. Для зашифрованных передач используйте ftp_ssl_connect() вместо ftp_connect().

Синтаксис ftp_fget()

ftp_fget(
    FTP\Connection $ftp,
    resource $stream,
    string $remote_filename,
    int $mode = FTP_BINARY,
    int $offset = 0
): bool
ПараметрОписание
$ftpСоединение, возвращённое ftp_connect() (и аутентифицированное через ftp_login()).
$streamОткрытый локальный файловый указатель, в который записываются загружаемые данные. Должен быть открыт для записи ('w', 'w+', 'a' и т.д.).
$remote_filenameПуть к файлу на FTP-сервере.
$modeРежим передачи: FTP_BINARY (по умолчанию с PHP 7.3) для любых нетекстовых файлов или FTP_ASCII для обычного текста с нормализацией окончаний строк.
$offsetПозиция в байтах в локальном потоке, с которой начинается запись — используется для возобновления частичной загрузки. По умолчанию 0.

Функция возвращает true в случае успеха и false в случае ошибки.

Загрузка файла с помощью ftp_fget()

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

<?php

// 1. Connect (returns false on failure)
$ftp = ftp_connect('ftp.example.com');
if ($ftp === false) {
    exit("Could not connect to the FTP server.\n");
}

// 2. Authenticate
if (!ftp_login($ftp, 'username', 'password')) {
    exit("FTP login failed.\n");
}

// Most networks need passive mode so the data channel works behind NAT/firewalls
ftp_pasv($ftp, true);

// 3. Open a local handle for writing
$handle = fopen('downloads/report.pdf', 'w');

// 4. Download into that handle (binary mode for a PDF)
if (ftp_fget($ftp, $handle, 'public/report.pdf', FTP_BINARY)) {
    echo "Download complete.\n";
} else {
    echo "Download failed.\n";
}

fclose($handle);
ftp_close($ftp);

Вызов ftp_pasv() для включения пассивного режима почти всегда необходим, когда клиент находится за брандмауэром или NAT, что является распространённым случаем; без него передача данных может зависнуть.

Выбор режима передачи

  • FTP_BINARY копирует файл побайтово. Используйте его для изображений, архивов, PDF-файлов, исполняемых файлов — всего, что не является обычным текстом. Это безопасный режим по умолчанию.
  • FTP_ASCII преобразует окончания строк в соответствии с целевой платформой. Используйте его только для текстовых файлов и только тогда, когда такое преобразование действительно нужно. Отправка бинарного файла в режиме ASCII повреждает его.

Возобновление прерванной загрузки

Параметр $offset позволяет продолжить прерванную загрузку. Откройте существующий частично загруженный файл в режиме дозаписи, определите количество уже имеющихся байт и укажите ftp_fget() начать запись с этого места:

<?php

$local = 'downloads/big.iso';

// Open in append mode so previously downloaded bytes are preserved
$handle = fopen($local, 'a');

// How many bytes we already have locally
$alreadyHave = file_exists($local) ? filesize($local) : 0;

if (ftp_fget($ftp, $handle, 'images/big.iso', FTP_BINARY, $alreadyHave)) {
    echo "Resumed and finished the download.\n";
}

fclose($handle);

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

Обработка ошибок

ftp_fget() возвращает только false — исключений не выбрасывает, — поэтому проверяйте возвращаемое значение каждого шага, а не только загрузки. Сравнение с помощью === позволяет избежать некорректной обработки ложного, но допустимого значения.

<?php

$handle = fopen('downloads/data.csv', 'w');
if ($handle === false) {
    exit("Could not open the local file for writing.\n");
}

if (ftp_fget($ftp, $handle, 'exports/data.csv', FTP_ASCII) === false) {
    // Common causes: wrong remote path, no read permission, or a dropped data channel
    echo "Failed to retrieve the file.\n";
} else {
    echo "File retrieved successfully.\n";
}

fclose($handle);

Распространённые ошибки

  • Передача пути вместо дескриптора. Второй аргумент должен быть ресурсом, полученным от fopen(). Если у вас есть путь, используйте ftp_get().
  • Забыли пассивный режим. За брандмауэром без вызова ftp_pasv() передача может молча зависнуть.
  • Неправильный режим передачи. Режим ASCII повреждает бинарные файлы; бинарный режим оставляет лишние окончания строк в текстовых файлах лишь на редких платформах, поэтому бинарный режим — более безопасный вариант по умолчанию.
  • Ресурсы не закрываются. Вызывайте fclose() и ftp_close(), чтобы буферы сбрасывались и соединение освобождалось.

Связанные функции

  • ftp_get() — загрузка по локальному пути (дескриптор не нужен).
  • ftp_fput() — аналог для загрузки на сервер из открытого дескриптора.
  • ftp_nb_fget() — неблокирующая загрузка в дескриптор.
  • ftp_connect() и ftp_login() — открытие и аутентификация сессии.

Практика

Практика
Какова функциональность ftp_fget() в PHP?
Какова функциональность ftp_fget() в PHP?
Was this page helpful?