W3docs

ftp_fget()

La función ftp_fget() de PHP descarga un archivo desde un servidor FTP y lo escribe en un manejador de archivo local ya abierto.

¿Qué es ftp_fget()?

ftp_fget() descarga un archivo desde un servidor FTP y lo escribe en un manejador de archivo local ya abierto. Esta es la diferencia clave con ftp_get(): ftp_get() recibe una ruta local y crea el archivo por ti, mientras que ftp_fget() recibe un recurso de archivo abierto (el valor devuelto por fopen()). Como tú controlas el manejador, ftp_fget() resulta muy útil cuando deseas escribir en un flujo que no es un archivo convencional — un flujo temporal (php://temp), un búfer en memoria, o un manejador que hayas posicionado con fseek().

Esta página cubre la firma de la función, una descarga completa y funcional, cómo elegir un modo de transferencia, cómo reanudar una descarga interrumpida y el manejo de errores necesario en código real.

La extensión FTP procedural sigue siendo parte de PHP. A partir de PHP 8.1, la conexión es un objeto FTP\Connection en lugar de un resource, pero el código que escribes no cambia. Para transferencias cifradas usa ftp_ssl_connect() en lugar de ftp_connect().

Sintaxis de ftp_fget()

ftp_fget(
    FTP\Connection $ftp,
    resource $stream,
    string $remote_filename,
    int $mode = FTP_BINARY,
    int $offset = 0
): bool
ParámetroDescripción
$ftpLa conexión devuelta por ftp_connect() (y autenticada con ftp_login()).
$streamUn puntero de archivo local abierto en el que se escriben los datos descargados. Debe estar abierto para escritura ('w', 'w+', 'a', etc.).
$remote_filenameRuta al archivo en el servidor FTP.
$modeModo de transferencia: FTP_BINARY (predeterminado desde PHP 7.3) para cualquier archivo que no sea texto plano, o FTP_ASCII para texto plano cuyas terminaciones de línea deben normalizarse.
$offsetPosición en bytes en el flujo local desde la que comenzar a escribir — se usa para reanudar una descarga parcial. El valor predeterminado es 0.

Devuelve true en caso de éxito y false en caso de fallo.

Descargar un archivo con ftp_fget()

Una descarga completa tiene cuatro pasos: conectar, iniciar sesión, abrir un manejador local y luego obtener el archivo. Cierra siempre tanto el manejador como la conexión cuando hayas terminado.

<?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);

Llamar a ftp_pasv() para habilitar el modo pasivo es casi siempre necesario cuando el cliente está detrás de un cortafuegos o NAT, que es el caso habitual; sin él, la transferencia de datos puede bloquearse.

Elegir un modo de transferencia

  • FTP_BINARY copia el archivo byte a byte. Úsalo para imágenes, archivos comprimidos, PDFs, ejecutables — cualquier cosa que no sea texto plano. Es el valor predeterminado seguro.
  • FTP_ASCII convierte las terminaciones de línea para que coincidan con la plataforma de destino. Úsalo solo para archivos de texto, y solo cuando realmente quieras esa conversión. Enviar un archivo binario en modo ASCII lo corrompe.

Reanudar una descarga interrumpida

El parámetro $offset te permite continuar una descarga que fue interrumpida. Abre el archivo parcial existente en modo de anexo, averigua cuántos bytes ya tienes y dile a ftp_fget() que comience a escribir desde ahí:

<?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);

Para archivos muy grandes puede que prefieras la variante no bloqueante ftp_nb_fget(), que devuelve el control a tu script entre fragmentos para que puedas mostrar el progreso.

Manejo de errores

ftp_fget() solo devuelve false — no lanza excepciones — así que comprueba el valor de retorno de cada paso, no solo el de la descarga. Comparar con === evita tratar un valor falsy pero válido de forma incorrecta.

<?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);

Errores comunes

  • Pasar una ruta en lugar de un manejador. El segundo argumento debe ser un recurso de fopen(). Si tienes una ruta, usa ftp_get() en su lugar.
  • Olvidar el modo pasivo. Detrás de un cortafuegos, si omites ftp_pasv() la transferencia puede bloquearse silenciosamente.
  • Modo de transferencia incorrecto. El modo ASCII daña los archivos binarios; el modo binario deja terminaciones de línea sueltas en archivos de texto solo en plataformas raras, por lo que binario es el valor predeterminado más seguro.
  • No cerrar los recursos. Llama a fclose() y ftp_close() para que se vacíen los búferes y se libere la conexión.

Funciones relacionadas

Práctica

Práctica
¿Cuál es la funcionalidad de la función ftp_fget() en PHP?
¿Cuál es la funcionalidad de la función ftp_fget() en PHP?
Was this page helpful?