应使用is_uploaded_file()而非file_exists()判断上传文件临时路径有效性,且必须先检查$_FILES'file' === UPLOAD_ERR_OK,再调用is_uploaded_file()确认后才执行move_uploaded_file()。

PHP中不能用file_exists()直接判断上传文件
上传文件临时路径($_FILES['xxx']['tmp_name'])是 PHP 写入的临时文件,但file_exists()在某些环境(如 SELinux、容器、NFS 挂载卷)下可能返回 false,即使文件真实存在。这不是你代码写错了,而是底层权限或文件系统行为导致的误判。
真正可靠的方式是结合is_uploaded_file()——它专为上传场景设计,会检查该文件是否由当前请求通过 HTTP POST 上传而来,并验证其临时文件状态是否合法。
-
is_uploaded_file($_FILES['file']['tmp_name'])返回true才表示上传成功且文件可读 - 如果返回
false,说明要么没上传、上传失败、被移动过、或路径被篡改(比如手动拼接了tmp_name) - 不要在调用
is_uploaded_file()前对tmp_name做任何字符串处理(如trim()、basename()),否则一定失败
上传失败时$_FILES的error值必须检查
仅靠is_uploaded_file()不够。用户可能点了上传但实际没选文件、超出了upload_max_filesize限制、或表单编码类型不对(enctype不是multipart/form-data),这些都会让$_FILES['xxx']['error']非零,此时tmp_name可能是空字符串或非法路径,is_uploaded_file()也会返回false,但原因完全不同。
- 常见错误码:
UPLOAD_ERR_NO_FILE(0 表示无错,1–8 是各种错误,如UPLOAD_ERR_INI_SIZE对应配置超限) - 务必先判断
$_FILES['file']['error'] === UPLOAD_ERR_OK,再调用is_uploaded_file() - 如果
error不为UPLOAD_ERR_OK,tmp_name不可信,直接跳过后续文件操作
移动文件前必须确认is_uploaded_file()为真
很多人习惯先move_uploaded_file()再检查是否成功,但这是危险的——如果tmp_name无效,move_uploaded_file()会静默失败并返回false,而你可能没捕获这个返回值,导致“上传成功”假象。
立即学习“PHP免费学习笔记(深入)”;
- 正确顺序:检查
error === UPLOAD_ERR_OK→ 调用is_uploaded_file($tmp)→ 为真才执行move_uploaded_file($tmp, $dest) -
move_uploaded_file()本身也有安全机制:只允许移动tmp_name指向的上传临时文件,不能移动任意路径,所以它和is_uploaded_file()是配套使用的 - 目标路径
$dest的父目录必须已存在且 PHP 有写权限,否则move_uploaded_file()也返回false,这和上传是否存在无关
别用$_FILES['xxx']['name']做存在性判断
$_FILES['xxx']['name']只是客户端传来的原始文件名,完全不可信。它可能为空、含路径遍历(如../../etc/passwd)、或根本没上传却伪造了字段。这个值和文件是否真实上传到服务器毫无关系。
曾有人写if (!empty($_FILES['file']['name'])) { ... }来判断上传,结果绕过所有校验,造成空文件移动或路径注入漏洞。
-
name只用于展示或生成新文件名(需严格过滤,如用pathinfo()取扩展名 + 白名单校验) - 判断“上传文件是否存在”,唯一可信依据只有
error码和is_uploaded_file()返回值 - 如果表单支持多文件上传,
$_FILES['files']['error']是数组,要逐项检查,不能只看第一个
if ($_FILES['file']['error'] === UPLOAD_ERR_OK
&& is_uploaded_file($_FILES['file']['tmp_name'])) {
move_uploaded_file($_FILES['file']['tmp_name'], '/path/to/save.jpg');
}
漏掉error检查或把is_uploaded_file()换成file_exists(),都可能在特定服务器上出问题——尤其是上线后换环境,这类细节最容易被忽略。



















