$_files为空或move_uploaded_file()失败,主因是表单漏enctype="multipart/form-data"、name键名不匹配、php配置file_uploads=off或大小超限、目标目录无写权限、误用非tmp_name路径、多文件时未按索引遍历$_files'field'[$i]等结构。

$_FILES 数组结构没搞清,就别碰 move_uploaded_file() —— 90% 的上传失败都卡在这一步。
为什么 $_FILES 是空的或报 Undefined index?
不是代码写错了,是表单或配置漏了关键项。
-
enctype="multipart/form-data"必须显式写在<form></form>标签里,漏掉或写成application/x-www-form-urlencoded就根本不会发文件数据 -
<input type="file" name="avatar">的name值必须和 PHP 中读的键名完全一致:$_FILES['avatar'],大小写、下划线、中横线都不能错 - PHP 配置要打开:
file_uploads = On;还要检查upload_max_filesize和post_max_size,比如设了2M却传 3MB,$_FILES就静默为空 - Nginx 用户额外注意:
client_max_body_size默认常为 1M,超限直接返回 413,PHP 根本收不到请求
move_uploaded_file() 总是返回 false 怎么办?
这不是函数用错了,是路径、权限或生命周期出了问题。
- 源路径只能是
$_FILES['xxx']['tmp_name'],其他任何拼接出来的字符串(包括$_POST['path']或硬编码路径)都会被拒绝 - 目标目录必须真实存在,且 Web 进程用户(如
www-data或nginx)有写权限;用is_writable($dir)检查,别靠chmod 777猜 - 临时文件只在当前请求内有效——存进 session、数据库、等下次再移?它早被 PHP 清理掉了
- Windows 下路径分隔符建议统一用
/或DIRECTORY_SEPARATOR,避免反斜杠被解析为转义
怎么真正校验上传文件,而不是“看起来安全”?
前端 accept、后缀名、$_FILES['type'] 全部可伪造,服务端必须做三层校验。
- 先看
$_FILES['xxx']['error'] === UPLOAD_ERR_OK(即0),非零值代表上传根本没成功,后续都不用做了 - 用
finfo_open(FILEINFO_MIME_TYPE)读实际 MIME,比如image/jpeg,不信任$_FILES['xxx']['type'] - 对图片加一层
getimagesize(),对 ZIP 用zip_open()尝试打开,验证是否真能解析 - 重命名必须做:
basename()防路径遍历(如../../etc/passwd),但还得生成唯一文件名(如uniqid() . '.' . $ext),避免覆盖或执行风险(如shell.php.jpg)
多文件上传时 $_FILES 结构怎么理解?
不是把多个文件塞进一个数组,而是字段维度优先重组,容易误读成“按上传顺序排列”。
-
<input type="file" name="photos[]" multiple>提交后,$_FILES['photos']是二维数组,结构为:['name']、['type']、['tmp_name']、['error']、['size']各自是一个等长数组 - 不能直接遍历
$_FILES['photos'],得用count($_FILES['photos']['name'])获取数量,再用索引取每个文件的完整信息 - 例如第 0 个文件的临时路径是
$_FILES['photos']['tmp_name'][0],错误码是$_FILES['photos']['error'][0] - 单文件上传用
$_FILES['photo'],多文件必须用$_FILES['photos']+ 索引,混用会出错
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











