frankenphp上传失败主因是$_files为空,核心在于max_memory_upload阈值过小(默认约2mb)、file_uploads被禁或nginx的client_max_body_size拦截;需验证upload_tmp_dir权限、目标目录可写及配置重启生效。

FrankenPHP 保存用户上传的文件,核心不是“怎么写代码”,而是“怎么让 $_FILES 不为空、临时文件能落盘、目标目录可写”。本地能传、服务器失败,90% 是上传链路某处被卡住,不是 PHP 逻辑问题。
为什么 $_FILES 始终为空
根本原因通常是 FrankenPHP 的上传内存阈值太小,或 file_uploads 被关了:
-
max_memory_upload默认仅约 2MB,超过就直接丢弃整个 multipart body,$_FILES清空且无报错 —— 这是 FrankenPHP 特有行为,和 PHP-FPM 完全不同 -
file_uploads = Off在php.ini中被误设(尤其 Docker 或 systemd 启动时加载了错误配置) -
post_max_size小于upload_max_filesize,导致 POST 在进入 PHP 前就被截断,页面可能直接 400 或空白 - 没重启 FrankenPHP:改完
php.ini必须systemctl restart frankenphp或frankenphp stop && frankenphp start
move_uploaded_file() 失败的常见路径问题
即使 $_FILES 有内容,move_uploaded_file() 仍可能静默失败,关键看三处权限与路径:
- 源路径:
$_FILES['file']['tmp_name']指向的临时文件,由upload_tmp_dir决定。FrankenPHP 默认用系统/tmp,但进程用户(如www-data)必须有写权限:sudo -u www-data touch /tmp/test测试是否可行 - 目标路径:你要保存到的目录(如
public/uploads/)必须存在,且属主为 FrankenPHP 运行用户:sudo chown www-data:www-data public/uploads,权限建议755 - 路径大小写敏感:Linux 下
Public/uploads和public/uploads是两个目录,框架自动拼路径时容易出错;检查$_FILES['file']['name']是否含非法字符(如../),需清洗
Nginx 反向代理时上传被拦截
FrankenPHP 常跑在 Nginx 后面,而 Nginx 自己会先拦一次大文件:
- 错误现象:上传时返回
413 Request Entity Too Large - 解决方法:在 Nginx 的
location @frankenphp或对应 proxy 块中加:client_max_body_size 50M; - 别只改
http或server级配置,必须确保该指令生效在实际转发到 FrankenPHP 的 location 块里 - 如果用 Caddy 作反向代理,对应指令是
body_limit 50mb
生产环境必须显式配置 upload_tmp_dir
依赖系统 /tmp 风险高,尤其启用了 PrivateTmp=true 的 systemd 服务或 SELinux:
- 创建专用目录:
sudo mkdir -p /var/tmp/frankenphp-upload - 赋权:
sudo chown www-data:www-data /var/tmp/frankenphp-upload && sudo chmod 755 /var/tmp/frankenphp-upload - 在
php.ini中设置:upload_tmp_dir = "/var/tmp/frankenphp-upload" - 验证是否生效:在 PHP 中
var_dump(ini_get('upload_tmp_dir')),必须输出你刚设的路径
最易忽略的是:FrankenPHP 的 upload_tmp_dir 配置不生效时,它不会报错,而是悄悄退回用内存缓存,一旦超限就丢文件 —— 所以必须手动验证路径是否真的被读取。上传大文件前,先用 curl -F "file=@test.zip" http://yoursite.tld/upload 测试,并立刻检查 upload_tmp_dir 目录下是否有临时文件生成。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











