$_files["xxx"]["tmp_name"]是php接收上传文件后生成的临时文件绝对路径,仅用于move_uploaded_file()安全搬运,脚本结束自动删除,但异常时可能残留需手动清理。

PHP 文件上传不是“直接存到目标目录”,而是先写入临时文件,再由你手动搬过去——这个临时环节是绝大多数问题的根源。
$_FILES 数组里的 tmp_name 是什么?
浏览器通过 multipart/form-data 把文件切成块发过来,PHP 接收后不做解析,直接把原始二进制内容完整写进系统临时目录(如 /tmp 或 Windows 的 C:\Windows\Temp),生成一个随机命名的临时文件,并把路径记在 $_FILES['xxx']['tmp_name'] 里。
这个路径不是你可控的,也不该被直接拼接进 web 可访问路径;它只供 move_uploaded_file() 使用一次。一旦脚本结束,PHP 会自动清理它——除非你没调用 move_uploaded_file(),或调用失败,那它就留在那里占空间、埋隐患。
-
tmp_name不是永久路径,不能file_get_contents()或copy()它(会失败或不安全) - 不能用
is_uploaded_file()判断后就直接include()或eval()——这是典型 WebShell 入口 - 如果 PHP 配置了
upload_tmp_dir,但目录不可写,$_FILES['xxx']['error']会是UPLOAD_ERR_NO_TMP_DIR或UPLOAD_ERR_CANT_WRITE
为什么必须用 move_uploaded_file() 而不是 rename() 或 copy()?
move_uploaded_file() 是唯一被 PHP 明确标记为“安全搬运”的函数。它内部做了两件事:检查源路径是否真是上传产生的临时文件(防止路径遍历伪造),再执行原子移动(避免竞态条件)。而 rename() 和 copy() 没这层校验。
- 用
rename()移动非临时文件(比如用户构造的../../etc/passwd)会绕过上传校验 -
copy()可能复制恶意内容,且不保证原子性——大文件上传中途失败,可能留下半截文件 - 即使
move_uploaded_file()返回false,也别假设临时文件还存在:它可能已被清理,也可能残留,但状态不确定
临时文件生命周期和常见陷阱
临时文件存在时间极短:从 PHP 接收完 POST 数据开始,到脚本执行结束(无论成功失败)就该被删掉。但实际中常因错误中断或配置问题导致残留。
- 脚本 fatal error(如内存溢出)或
exit()太早,可能导致move_uploaded_file()没执行,临时文件滞留 -
upload_max_filesize或post_max_size设得太小,文件根本进不了$_FILES,error是UPLOAD_ERR_INI_SIZE,连tmp_name都为空 - Web 服务器(如 Nginx)自身也有 body size 限制(
client_max_body_size),它会在 PHP 之前拦截请求,此时$_FILES为空,$_SERVER['CONTENT_LENGTH']却可能显示很大值
真正要盯住的不是“怎么传”,而是“谁在什么时候删了那个临时文件”——所有上传逻辑都得围绕这个不可见的临时文件转,漏掉任何一环,轻则失败,重则留后门。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











