ftp_put()上传文件前必须先ftp_login()并ftp_chdir()切换到目标目录,远程路径需写绝对路径,目录不存在则失败;须启用ftp_pasv()、设置超时;应传临时名再ftp_rename()原子替换,避免覆盖损坏。

用 ftp_put() 上传文件前必须主动登录并切换目录
很多人调用 ftp_put() 失败,根本原因不是函数写错了,而是没意识到 FTP 操作是状态依赖的:必须先 ftp_login(),再用 ftp_chdir() 进入目标目录。FTP 服务器不会自动把文件扔到你“以为”的路径下。
- 默认工作目录通常是用户根目录(如
/home/username/),不是网站根目录(如/var/www/html/) -
ftp_put()的第二个参数是**远程路径**,它不支持相对路径拼接,比如传"./css/style.css"很可能失败,得写成"/var/www/html/css/style.css" - 如果目标目录不存在,
ftp_put()不会自动创建,会直接返回false,且无明确错误提示
替换文件时要注意被动模式(PASV)和连接超时
内网或带防火墙的服务器上传失败,八成卡在数据连接阶段——这和 FTP 主动/被动模式有关。PHP 默认用主动模式,但多数现代网络环境(尤其是客户端在 NAT 后)要求开启被动模式。
- 务必在
ftp_login()后立即调用ftp_pasv($conn, true),否则大文件上传中途断连很常见 - 上传大文件或慢速网络下,需提前设置超时:
ftp_set_option($conn, FTP_TIMEOUT_SEC, 120),默认 90 秒经常不够 - 注意:
ftp_pasv()必须在每次登录后调用,重连时不继承上一次的状态
文件覆盖没有“原子性”,出错就留半截文件
FTP 协议本身不支持“先传新文件、再原子替换”的操作。直接 ftp_put() 到已有文件名,结果就是边写边覆盖——如果中断,线上就跑着一个损坏的文件。
- 稳妥做法是上传到临时名(如
"style.css.tmp"),再用ftp_rename()替换原文件 -
ftp_rename()在大多数 FTP 服务端是原子操作,失败时原文件不受影响 - 别依赖
ftp_delete()先删再传——删成功了但上传失败,就彻底没文件了
PHP 8.1+ 已废弃 ftp_connect() 等函数,但还没移除
官方标记为 Deprecated 不等于不能用,只是提醒你:未来版本真会砍掉。现在还能跑,但得心里有数。
立即学习“PHP免费学习笔记(深入)”;
- 错误信息长这样:
Deprecated: ftp_connect(): Using ftp:// wrapper is deprecated - 替代方案不是简单换函数,而是改用
cURL+ FTP URL(如curl -T file.txt ftp://u:p@host/path/),或引入phpseclib做 SFTP(更安全,也更稳) - 如果还在用老旧托管环境(如某些共享主机),可能压根不支持 cURL FTP,那就只能继续扛着 deprecated 警告用,但务必加
@抑制警告(仅限生产环境兜底)
ftp_put() 返回 true 不代表文件真到了指定位置。











