move_uploaded_file()返回true才表示上传成功,否则为false;必须用if判断其返回值,结合$_files'xxx'===0、is_uploaded_file()、finfo_open()校验真实mime、basename()防路径遍历及扩展名白名单等完整验证链确保安全。

直接对 $_FILES 数组做校验,不能只看文件名或临时路径,必须结合 move_uploaded_file() 前的完整验证链。
检查 upload 函数返回值是否为 true
PHP 的 move_uploaded_file() 会返回布尔值,失败时返回 false。很多代码只调用它却不判断结果,导致“看似上传成功”实则被丢弃或写入失败。
- 始终用
if (move_uploaded_file(...)) { ... }包裹后续逻辑 - 失败时记录错误(如
error_get_last())、返回明确提示,不要静默跳过
验证 $_FILES['xxx']['error'] 状态码
$_FILES 中每个文件项的 error 键是核心校验入口,它反映的是上传过程本身的系统级结果,比后缀、MIME 类型更可信。
本套教程,以一个真实的学校教学管理系统为案例,手把手教会您如何在一张白纸上,从零开始,一步一步的用ThinkPHP5框架快速开发出一个商业项目,让您快速入门TP5项目开发。
-
0:上传成功(唯一可继续处理的状态) -
1/2:超出了 php.ini 中upload_max_filesize或MAX_FILE_SIZE隐藏字段限制 -
3:文件只有部分被上传(网络中断等) -
4:没有文件被上传(表单为空或 name 不匹配) -
6/7/8:临时目录缺失、写入失败、上传被扩展中断等
拒绝仅靠 $_FILES['xxx']['type'] 判断 MIME
$_FILES['xxx']['type'] 是浏览器提交的字符串,完全不可信,可任意伪造。必须用服务端方式重判:
- 用
finfo_open(FILEINFO_MIME_TYPE)读取文件头识别真实类型 - 对图片还可加
getimagesize()辅助验证(但注意它可能触发 PHP 漏洞旧版本风险) - 白名单控制:只允许
image/jpeg、application/pdf等明确需要的类型
校验文件名与路径安全性
用户传来的原始文件名($_FILES['xxx']['name'])可能含路径遍历(如 ../../etc/passwd)或危险扩展名(如 .php)。
- 剥离路径:用
basename($_FILES['xxx']['name']) - 强制重命名:不依赖原名,用时间戳+随机字符串生成新文件名
- 扩展名白名单:从重命名后的文件名中提取后缀,严格比对(如
in_array($ext, ['jpg','png','pdf'])) - 禁止可执行扩展:如
.php、.phtml、.htaccess等一律拒收










