php文件上传失败主因是upload_max_filesize与post_max_size未对齐或web服务器(如nginx)拦截:需同步调大二者并重启php-fpm,确认nginx的client_max_body_size及apache的limitrequestbody匹配,再校验代码中$_files['error']、临时目录权限与max_input_time超时设置。

PHP文件上传失败,八成不是代码写错了,而是upload_max_filesize和post_max_size没对齐,或者Nginx在半路就把请求拦下了。光改PHP配置不碰Web服务器,等于给门装了锁却忘了关窗户。
为什么改了php.ini还是上传失败
常见现象是选了10MB文件,$_FILES为空,或$_FILES['file']['error']返回UPLOAD_ERR_INI_SIZE(值为1)。这不是前端没传,是PHP在解析请求体前就拒收了。
-
upload_max_filesize管单个文件上限,比如设为50M -
post_max_size必须≥upload_max_filesize,因为整个POST请求包含文件+其他字段,建议设为52M - 改完必须重启PHP-FPM(或Apache),
nginx -s reload不够——它不重载PHP配置 - 用
ini_get('upload_max_filesize')或phpinfo()确认真实生效值,别只信配置文件
Nginx/Apache层拦截导致413错误
即使PHP和代码都放行,Nginx默认client_max_body_size只有1MB,请求根本到不了PHP,直接返回413 Request Entity Too Large。Apache同理,LimitRequestBody可能被虚拟主机或.htaccess悄悄限制。
- Nginx:在
server或location块里加client_max_body_size 50M;,然后nginx -t && nginx -s reload - Apache:检查
.htaccess或虚拟主机配置,确保没有LimitRequestBody 1048576这类限制;如有,改成LimitRequestBody 52428800(50MB字节) - 云环境(如ALB、Cloudflare)也可能有body size或超时限制,直连后端测试可快速排除
PHP代码里怎么安全校验大小和类型
配置只是底线,代码校验才是防线。尤其多文件上传时,$_FILES结构容易误读,导致校验失效。
- 正确访问单个文件大小:
$fileSize = $_FILES['files']['size'][$i],不是$_FILES['files'][$i]['size'] - 必须先检查
$_FILES['files']['error'][$i]是否为0,否则size可能不可靠(比如UPLOAD_ERR_PARTIAL时size为0) - 白名单扩展名验证要配合
finfo_file()检测真实MIME,仅靠$_FILES['file']['type']或后缀易被绕过 - 重命名用
uniqid() . '_' . bin2hex(random_bytes(8)),避免冲突和路径遍历
大文件上传不能只靠调大配置
把upload_max_filesize设成2G,不代表用户能稳定传上去。网络抖动、超时、内存溢出会直接中断,且无进度反馈。
- 前端必须分片:用
File.slice()切块(如每片5MB),携带chunk_index、total_chunks、file_id等元数据 - 后端接收分片存临时目录,命名如
{file_id}_part_003,合并前校验所有分片是否存在、大小是否匹配 - 进度条依赖
XMLHttpRequest.upload.onprogress,不能只靠后端返回百分比——那是合并阶段的进度 - 断点续传需记录已上传分片索引,用Redis或数据库存状态,避免重复上传
最常被忽略的一点:max_input_time控制的是PHP解析整个输入(含文件上传)的最长时间,不是脚本执行时间。上传1GB文件耗时超过默认60秒,它就会在move_uploaded_file()之前就中止,报错却像“文件未上传”。这个值必须和max_execution_time一起调,而且得比预期上传时间更宽裕。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











