
PHP 8.5 多文件上传的 $_FILES 结构变了没?
没变。PHP 8.5 没改动 $_FILES 的数组结构,和 PHP 7.4/8.0/8.1 一致——但很多人栽在没看清它天然就是「嵌套二维」,误当一维处理。
表单提交多个 <input type="file" name="photos[]" multiple> 后,$_FILES['photos'] 是个关联数组,含 name、tmp_name、error 等键,每个键下才是按顺序排列的文件项(比如 $_FILES['photos']['name'][0] 是第一个文件名)。
- 错误写法:
foreach ($_FILES['photos'] as $file)→ 遍历的是'name'、'tmp_name'这些字段,不是文件 - 正确做法:先用
count($_FILES['photos']['name'])得到文件数,再按索引遍历 - 注意
$_FILES['photos']['error'][i]必须逐个检查,一个失败不影响其他
怎么安全地移动多个上传文件?
不能直接对整个 $_FILES['files']['tmp_name'] 调用 move_uploaded_file() —— 它只接受单个字符串路径。必须拆开逐个处理。
关键点不在 PHP 版本,而在路径拼接和扩展名校验:
立即学习“PHP免费学习笔记(深入)”;
技术上面应用了三层结构,AJAX框架,URL重写等基础的开发。并用了动软的代码生成器及数据访问类,加进了一些自己用到的小功能,算是整理了一些自己的操作类。系统设计上面说不出用什么模式,大体设计是后台分两级分类,设置好一级之后,再设置二级并选择栏目类型,如内容,列表,上传文件,新窗口等。这样就可以生成无限多个二级分类,也就是网站栏目。对于扩展性来说,如果有新的需求可以直接加一个栏目类型并新加功能操作
- 用
pathinfo($filename, PATHINFO_EXTENSION)提取扩展名,别信$_FILES['files']['type'](浏览器可伪造) - 目标路径要绝对,建议用
__DIR__ . '/uploads/' . $safe_name,避免相对路径出错 - 每次调用
move_uploaded_file()后,检查返回值是否为true,否则记录$_FILES['files']['error'][$i]对应的错误码 - 常见错误码:
UPLOAD_ERR_OK(0)、UPLOAD_ERR_INI_SIZE(1)、UPLOAD_ERR_NO_FILE(4)
for ($i = 0; $i < count($_FILES['photos']['name']); $i++) {
if ($_FILES['photos']['error'][$i] === UPLOAD_ERR_OK) {
$ext = strtolower(pathinfo($_FILES['photos']['name'][$i], PATHINFO_EXTENSION));
if (in_array($ext, ['jpg', 'png', 'gif'])) {
$target = __DIR__ . '/uploads/' . uniqid() . '.' . $ext;
move_uploaded_file($_FILES['photos']['tmp_name'][$i], $target);
}
}
}
PHP 8.5 里 max_file_uploads 和 post_max_size 还管用吗?
完全管用,而且比以前更关键。PHP 8.5 没放宽限制,反而因默认启用严格类型和更早报错,让超限问题暴露得更快。
两个配置项是硬门槛,前端加再多 multiple 也没用:
-
max_file_uploads控制单次请求最多允许几个文件(默认 20),超过的部分会被静默丢弃,$_FILES里根本不会出现 -
post_max_size和upload_max_filesize共同决定总大小上限;例如设了upload_max_filesize = 2M、post_max_size = 8M,那最多传 3 个 2MB 文件,第 4 个即使很小也会失败 - 运行时可通过
ini_get('max_file_uploads')检查实际生效值,别只看 php.ini 注释
为什么上传大文件时 $_FILES 为空?
不是代码问题,是请求根本没进 PHP。Nginx/Apache 在到达 PHP 前就截断了。
尤其 PHP 8.5 + Nginx 组合下,漏配 Nginx 的 client_max_body_size 是最常见原因:
- Nginx 默认
client_max_body_size是 1MB,比post_max_size还小,优先触发 413 错误 - Apache 的
LimitRequestBody也要同步调大,否则 PHP 根本收不到原始数据 - PHP-FPM 场景下,还要确认
request_terminate_timeout是否过短,大文件上传超时会导致连接中断 - 调试时 curl 测试比浏览器更可靠:
curl -F "photos[]=@a.jpg" -F "photos[]=@b.jpg" http://localhost/upload.php
多文件上传真正的复杂点不在语法,而在错误分支的覆盖程度——error 数组里混着成功和失败项,tmp_name 可能为空串,name 可能带路径或空格。别省略任何一项校验。










