PHP隐式Curl FTP上传本地正常,生产环境文件为空问题排查
可能导致生产环境FTPS上传文件为空的原因及排查方向
以下是针对你的隐式FTPS上传代码,本地正常但生产环境上传空文件的常见问题点:
1. 本地源文件权限问题
生产环境中,PHP运行进程(如www-data、nginx等)可能没有读取$srcFile的权限。即便fopen未抛出明显错误,也会导致无法读取文件内容,最终上传空文件。
- 排查:执行
ls -l $srcFile查看文件权限,确保PHP进程所属用户有读权限;或临时给文件加全局读权限(chmod 644 $srcFile)测试。
2. 文件大小获取失效
代码中依赖filesize($srcFile)设置CURLOPT_INFILESIZE,若生产环境中该函数返回0(比如文件动态生成后未刷新缓存、权限不足导致无法获取大小),远程服务器会认为文件长度为0,直接创建空文件。
- 排查:在代码中添加
var_dump(filesize($srcFile))检查返回值;改用fstat($fp)获取文件大小,避免依赖filesize的缓存机制:$fp = fopen($srcFile, 'r'); $stat = fstat($fp); curl_setopt($curlhandle, CURLOPT_INFILESIZE, $stat['size']);
3. FTPS隐式模式配置不匹配
隐式FTPS默认使用990端口,且要求连接建立时立即启用SSL。你的代码存在两个潜在问题:
- 默认端口设为21(显式FTP端口),若生产环境远程服务器强制隐式模式,会导致SSL握手异常,数据传输中断;
CURLOPT_FTP_SSL设为CURLFTPSSL_TRY(尝试SSL),而非强制要求SSL的CURLFTPSSL_ALL;CURLOPT_FTPSSLAUTH设为CURLFTPAUTH_TLS,但隐式模式可能需要CURLFTPAUTH_SSL。- 排查:将端口改为990,调整SSL参数:
curl_setopt($curlhandle, CURLOPT_PORT, 990); curl_setopt($curlhandle, CURLOPT_FTP_SSL, CURLFTPSSL_ALL); curl_setopt($curlhandle, CURLOPT_FTPSSLAUTH, CURLFTPAUTH_SSL);
4. FTP被动模式未启用
生产环境服务器通常处于防火墙或NAT之后,主动模式FTP的数据连接会被拦截,导致文件内容无法传输。你的代码未显式设置被动模式,依赖CURL默认行为,可能在生产环境失效。
- 排查:添加被动模式配置:
curl_setopt($curlhandle, CURLOPT_FTPPORT, '-'); // 启用被动模式 curl_setopt($curlhandle, CURLOPT_FTP_USE_EPSV, true); // 优先使用EPSV
5. PHP open_basedir限制
若生产环境PHP配置了open_basedir,且$srcFile不在允许的目录范围内,fopen会静默失败(仅返回false),但代码未检查该返回值,导致上传空内容。
- 排查:查看
php.ini中的open_basedir配置,确保源文件所在目录在允许列表内;或添加fopen错误检查:$fp = fopen($srcFile, 'r'); if (!$fp) { die("无法打开源文件: $srcFile"); }
6. CURL版本或依赖差异
本地与生产环境的CURL版本、SSL库(如OpenSSL)版本不一致,旧版本可能存在隐式FTPS传输的bug,导致数据未完整发送。
- 排查:执行
curl --version查看生产环境版本,对比本地版本;若版本过旧,升级CURL及依赖库。
7. 错误日志缺失
你的代码仅获取curl_error但未输出或记录,生产环境中可能存在CURL错误(如SSL握手失败、连接超时)但未被发现,导致上传中断。
- 排查:添加完整错误日志记录:
$result = curl_exec($curlhandle); if (!$result) { error_log("CURL上传错误: " . curl_error($curlhandle) . ", 错误码: " . curl_errno($curlhandle)); } curl_close($curlhandle); // 补充关闭句柄,避免资源泄漏 fclose($fp); // 关闭文件句柄
内容的提问来源于stack exchange,提问作者user2942945
相关产品推荐
相关产品推荐

