在Yii框架中实现FTP上传需集成Nicolab/php-ftp-client库,配置被动模式与二进制传输,按单文件、整目录或带重试方式上传,并校验远程文件大小确保完整性。

在Yii框架中实现FTP上传功能,需绕过框架默认的本地文件存储机制,手动集成FTP客户端完成远程传输,避免因路径权限、临时目录清理或HTTP超时导致上传中断。
选择并安装FTP客户端库
使用 Nicolab/php-ftp-client 库,它轻量、无依赖、支持被动模式与二进制传输,比原生 ftp_* 函数更易维护。
执行命令安装:composer require nicolab/php-ftp-client。
若项目已禁用 allow_url_fopen 或启用了 open_basedir 限制,该库仍可正常工作;而原生 FTP 扩展在部分共享主机上已被禁用,【务必确认 phpinfo() 中 ftp 支持为 enabled】。
配置FTP连接参数
在 config/params.php 中添加以下配置:
'ftp' => [ 'host' => '192.168.10.50', 'port' => 21, 'username' => 'upload_user', 'password' => 'SecurePass2026!', 'passive' => true, 'timeout' => 60, ]
注意:不要将密码硬编码在控制器里;【passive 模式必须开启,否则内网/NAT 环境下 LIST 命令会失败】。
编写上传逻辑(以控制器 action 为例)
方法一:单文件上传
第一步:获取上传的 UploadedFile 实例,并验证是否有效。
第二步:生成唯一远程文件名,例如 date('Ymd_His') . '_' . $file->baseName . '.' . $file->extension,防止覆盖。
第三步:实例化 FTP 客户端,调用 connect() → login() → put() 三步完成传输,put() 第三个参数必须为 FTP_BINARY,否则图片、PDF 等二进制文件会损坏。
方法二:整目录上传(如日志归档、静态资源同步)
使用 putAll($localDir, $remoteDir),但需确保 $localDir 是绝对路径(可用 Yii::getAlias('@runtime/uploads') 获取),且远程目录已存在——该方法不会自动创建父级路径。
方法三:带重试的健壮上传
对 put() 封装三层重试逻辑,每次间隔 1.5 秒,失败后清除已传部分(调用 delete($remoteFile)),避免残留碎片文件。
处理上传后校验与错误响应
上传成功后立即调用 size($remoteFile) 对比本地 $file->size,不一致则抛出异常并记录日志。
不要仅依赖 put() 返回的 true,某些 FTP 服务器在磁盘满时仍返回成功,但实际写入截断。
前端收到 200 响应前,后端必须完成校验;否则用户以为上传成功,实则文件损坏。


















