PHP FTP
FTP en PHP permite conectarse a servidores remotos para transferir, listar y gestionar archivos mediante la extensión ext-ftp integrada.
Introducción
FTP (File Transfer Protocol) es un protocolo de red estándar para transferir archivos entre un cliente y un servidor a través de una conexión TCP. PHP incluye una extensión FTP integrada (ext-ftp) que permite a tus scripts iniciar sesión en un servidor remoto y mover archivos de forma programática — útil para desplegar recursos, sincronizar copias de seguridad o extraer feeds de datos desde el servidor de un socio.
Este capítulo cubre el flujo de trabajo completo: conectar, iniciar sesión, cambiar al modo pasivo, subir y descargar archivos, listar y gestionar archivos remotos, y finalmente cerrar la conexión correctamente. También explica las advertencias de seguridad que debes conocer antes de usar FTP simple en producción.
Nota de seguridad primero. El FTP simple envía tu nombre de usuario, contraseña y el contenido de los archivos sin cifrar. Para cualquier dato sensible, usa
ftp_ssl_connect()(FTP sobre TLS) o prefiere SFTP (SSH File Transfer Protocol), que la extensión FTP no soporta — usa la extensión PHP SSH2 o una librería como phpseclib para SFTP.
El flujo de trabajo típico de FTP
Todo script FTP sigue la misma estructura, independientemente de la operación que realices:
- Conectar al servidor —
ftp_connect()(oftp_ssl_connect()para FTPS). - Autenticar —
ftp_login(). - Configurar — generalmente
ftp_pasv($conn, true)para habilitar el modo pasivo. - Transferir / gestionar archivos —
ftp_put(),ftp_get(),ftp_nlist(), etc. - Cerrar —
ftp_close().
Conectarse a un servidor FTP
Establece una conexión con ftp_connect(). Recibe el nombre de host (y opcionalmente el puerto y el tiempo de espera) y devuelve un objeto FTP\Connection en caso de éxito (un recurso antes de PHP 8.1), o false en caso de error.
<?php
$conn = ftp_connect("ftp.example.com", 21, 10); // host, port, timeout (seconds)
if ($conn === false) {
die("Could not connect to FTP server");
}
echo "Connected.";Ten en cuenta que conectarse no inicia sesión — en este punto tienes un canal anónimo y sin autenticar. Aún debes llamar a ftp_login() antes de que el servidor te permita hacer algo útil.
Usar FTPS (FTP sobre TLS)
Para cifrar los canales de control y datos, reemplaza ftp_connect() por ftp_ssl_connect(). El resto de la API es idéntico:
<?php
$conn = ftp_ssl_connect("ftp.example.com");
if ($conn === false) {
die("Could not open a secure FTP connection");
}Iniciar sesión y modo pasivo
Después de conectarte, autentícate con ftp_login(). Para servidores públicos que permiten acceso anónimo, usa el nombre de usuario anonymous con una contraseña similar a un correo electrónico.
<?php
$conn = ftp_connect("ftp.example.com");
if (!ftp_login($conn, "username", "password")) {
ftp_close($conn);
die("Login failed");
}
// Most networks behind a firewall/NAT require passive mode.
ftp_pasv($conn, true);
echo "Logged in.";Por qué importa el modo pasivo. En el modo activo, el servidor abre una conexión de datos de vuelta a tu cliente, lo que los firewalls y routers NAT casi siempre bloquean. En el modo pasivo, el cliente abre la conexión de datos al servidor, por lo que funciona detrás de firewalls. Como regla general, llama a ftp_pasv($conn, true) justo después de iniciar sesión. Debe establecerse después de ftp_login(), no antes.
Subir archivos
Usa ftp_put() para enviar un archivo local al servidor. Su firma es ftp_put($conn, $remote_file, $local_file, $mode), donde $mode es FTP_BINARY o FTP_ASCII.
<?php
$conn = ftp_connect("ftp.example.com");
ftp_login($conn, "username", "password");
ftp_pasv($conn, true);
if (ftp_put($conn, "/public_html/report.pdf", "report.pdf", FTP_BINARY)) {
echo "Upload successful";
} else {
echo "Upload failed";
}
ftp_close($conn);FTP_BINARY vs FTP_ASCII. Usa FTP_BINARY para todo lo que no sea texto plano — imágenes, PDFs, archivos comprimidos, ejecutables — porque el modo ASCII reescribe los finales de línea y corromperá datos binarios. Usa FTP_ASCII solo cuando quieras específicamente que los finales de línea se traduzcan entre plataformas para archivos de texto. En caso de duda, elige FTP_BINARY; es la opción segura por defecto.
Para archivos grandes puedes subir de forma no bloqueante con ftp_nb_put(), lo que permite que tu script realice otras tareas entre fragmentos.
Descargar archivos
ftp_get() recupera un archivo remoto al sistema de archivos local. El orden de los argumentos es ftp_get($conn, $local_file, $remote_file, $mode) — nota que el destino local va primero, lo contrario de ftp_put(). Confundir estos es el error de FTP más común.
<?php
$conn = ftp_connect("ftp.example.com");
ftp_login($conn, "username", "password");
ftp_pasv($conn, true);
// local_file first, then remote_file
if (ftp_get($conn, "backup.zip", "/backups/backup.zip", FTP_BINARY)) {
echo "Download successful";
} else {
echo "Download failed";
}
ftp_close($conn);Listar y gestionar archivos remotos
La extensión FTP hace mucho más que transferir archivos. Las funciones de gestión más comunes incluyen:
| Función | Propósito |
|---|---|
ftp_nlist($conn, $dir) | Array con los nombres de archivos en un directorio |
ftp_rawlist($conn, $dir) | Listado detallado al estilo ls -l |
ftp_size($conn, $file) | Tamaño del archivo en bytes (-1 en caso de error) |
ftp_mkdir($conn, $dir) | Crear un directorio |
ftp_rmdir($conn, $dir) | Eliminar un directorio (vacío) |
ftp_delete($conn, $file) | Eliminar un archivo |
ftp_rename($conn, $from, $to) | Renombrar / mover un archivo |
ftp_chdir($conn, $dir) | Cambiar el directorio de trabajo |
ftp_pwd($conn) | Directorio de trabajo actual |
ftp_chmod($conn, 0644, $file) | Cambiar permisos del archivo |
<?php
$conn = ftp_connect("ftp.example.com");
ftp_login($conn, "username", "password");
ftp_pasv($conn, true);
$files = ftp_nlist($conn, "/public_html");
foreach ($files as $file) {
echo $file, " — ", ftp_size($conn, $file), " bytes\n";
}
ftp_close($conn);Cerrar la conexión
Siempre libera la conexión con ftp_close() cuando hayas terminado. Envolver el flujo de trabajo en try/finally garantiza que el socket se cierre incluso si se lanza un error a mitad del proceso:
<?php
$conn = ftp_connect("ftp.example.com");
if (!$conn || !ftp_login($conn, "username", "password")) {
die("Connection or login failed");
}
try {
ftp_pasv($conn, true);
ftp_put($conn, "/public_html/index.html", "index.html", FTP_BINARY);
} finally {
ftp_close($conn);
}Buenas prácticas y errores comunes
- Prefiere FTPS o SFTP. Nunca envíes credenciales por FTP simple a través de internet público.
- Siempre habilita el modo pasivo (
ftp_pasv) a menos que tengas una razón específica para no hacerlo. - Elige el modo de transferencia correcto —
FTP_BINARYpara datos binarios,FTP_ASCIIsolo para texto donde se desee traducir los finales de línea. - Presta atención al orden de los argumentos —
ftp_putes(remote, local),ftp_getes(local, remote). - Siempre cierra la conexión con
ftp_close(). - Comprueba cada valor de retorno. Las funciones FTP devuelven
falseen caso de error en lugar de lanzar excepciones, por lo que es fácil pasar por alto fallos silenciosos. ext-ftpdebe estar habilitado. Confirma conextension_loaded('ftp'); si devuelvefalse, habilita la extensión en tuphp.ini.
Temas relacionados
- Manejo de archivos en PHP — lectura y escritura de archivos locales.
- Subida de archivos en PHP — manejo de subidas desde formularios HTTP.
- Sistema de archivos en PHP — el conjunto más amplio de funciones del sistema de archivos.
- Excepciones en PHP — manejo estructurado de errores con
try/finally.