PHP FTP

Connecting, logging in, transfer, and passive mode.

Intermediate
Key PointsFTP sends passwords in clear text — use SFTP or FTPS when possible.

Functions

FunctionPurpose
ftp_connect连接(默认 21 端口)
ftp_ssl_connectFTPS 显式加密连接
ftp_login登录
ftp_pasv切换被动模式
ftp_get下载文件
ftp_put上传文件
ftp_nlist列目录(仅文件名)
ftp_mlsd列目录(含元信息)
ftp_delete删文件
ftp_mkdir建目录
ftp_size文件大小
ftp_close关闭连接

Connect and log in

PHP
<?php
$conn = ftp_connect("ftp.example.com", 21, 5);

if ($conn === false) {
    exit("连接失败");
}

$ok = @ftp_login($conn, "user", "password");
if (!$ok) {
    ftp_close($conn);
    exit("登录失败");
}

// 被动模式:几乎必开
ftp_pasv($conn, true);

echo "已登录,被动模式已开启\n";

ftp_close($conn);
Output
已登录,被动模式已开启
Passive mode is mandatory. In active mode the server dials back to the client, which fails behind NAT or a firewall — the symptom is "login works, listing hangs".

Transfer

PHP
<?php
$local = __DIR__ . "/upload.txt";
file_put_contents($local, "hello ftp\n");

$conn = ftp_connect("ftp.example.com", 21, 5);
ftp_login($conn, "user", "password");
ftp_pasv($conn, true);

// 上传(FTP_BINARY 传二进制,FTP_ASCII 传文本)
$ok = ftp_put($conn, "/remote/upload.txt", $local, FTP_BINARY);
echo $ok ? "上传成功" : "上传失败", "\n";

// 下载
$back = __DIR__ . "/download.txt";
if (ftp_get($conn, $back, "/remote/upload.txt", FTP_BINARY)) {
    echo "下载成功: " . filesize($back) . " 字节\n";
}

ftp_close($conn);
@unlink($local);
@unlink($back);
Output
上传成功
下载成功: 10 字节

FTP_ASCII converts line endings and suits plain text only. **Images, archives and binaries need FTP_BINARY** or they corrupt.

Directory operations

PHP
<?php
$conn = ftp_connect("ftp.example.com", 21, 5);
ftp_login($conn, "user", "password");
ftp_pasv($conn, true);

$list = ftp_nlist($conn, "/remote");
echo count($list) . " 项\n";

// 带元信息(部分服务器不支持 MLSD)
$mlsd = @ftp_mlsd($conn, "/remote");
if ($mlsd !== false) {
    foreach (array_slice($mlsd, 0, 2) as $f) {
        echo $f["name"] . " " . $f["type"] . "\n";
    }
} else {
    echo "服务器不支持 MLSD\n";
}

ftp_close($conn);
Output
3 项
upload.txt file
backup dir
ftp_nlist returns paths, not bare names — which form depends on the server. Apply basename yourself.

Security notes

  • FTP is plaintext —— passwords travel in the clear; use FTPS or SFTP
  • No built-in SFTP —— use phpseclib or the ssh2 extension
  • Never make upload dirs executable —— an uploaded .php is a webshell
  • No hardcoded credentials —— environment variables or a secret manager
A leaked FTP account lets an attacker upload a .php file and take the server. Scope FTP accounts to a directory with script execution disabled.

Friends & Partners