$_FILES'file_input_name'是原始文件名,由客户端控制、不可信,含路径遍历或非法字符风险,必须用basename()过滤并重命名后使用。

$_FILES 里哪个键是原始文件名
PHP 上传后,$_FILES['file_input_name']['name'] 就是浏览器提交的原始文件名(含扩展名)。它来自 HTTP 请求头中的 filename 字段,未经服务端处理,也不代表服务器上最终保存的路径或名称。
注意:$_FILES['file_input_name']['name'] 完全由客户端控制,不可信。用户可手动修改表单、用 curl 构造任意字符串,比如传 ../../../etc/passwd 或带空格/中文/特殊符号的文件名。
- 如果表单字段是
<input type="file" name="avatar">,就用$_FILES['avatar']['name'] - 多文件上传时(
name="photos[]"),$_FILES['photos']['name'][0]是第一个文件的原始名 - 该值不经过
move_uploaded_file()修改,也不会自动过滤路径分隔符
为什么不能直接用 $_FILES['name'] 做保存路径
因为原始文件名可能含非法字符、路径遍历片段、重复扩展名,甚至空字符串。直接拼接进 file_put_contents() 或 move_uploaded_file() 路径会导致写入错误、覆盖系统文件、或触发 open_basedir 限制。
常见出错现象:Warning: move_uploaded_file(): Unable to move ... No such file or directory,往往是因为 $_FILES['name'] 含 / 或 ../,导致目标路径解析失败。
立即学习“PHP免费学习笔记(深入)”;
- 必须过滤:用
basename()截掉路径部分,如basename($_FILES['file']['name']) - 建议重命名:生成唯一前缀(如
uniqid() . '_' . time()),再保留安全扩展名 - 扩展名必须从
finfo_file()或mime_content_type()二次校验,不能只靠pathinfo($name, PATHINFO_EXTENSION)
中文/emoji 文件名在不同环境下的表现
Windows 浏览器(Edge/Chrome)通常用 UTF-8 编码文件名;macOS Safari 可能用 UTF-8 加 NFD 归一化;旧版 IE 用系统编码(如 GBK),导致 $_FILES['name'] 出现乱码。PHP 默认不转码,原样接收字节流。
后果:直接 file_exists() 或 move_uploaded_file() 中文名会失败(尤其在 Linux + ext4 文件系统下),因为底层不识别编码歧义。
- 稳妥做法:一律重命名,避免依赖原始名的编码一致性
- 若必须保留原始语义,可用
mb_convert_encoding($name, 'UTF-8', 'auto')尝试转换,但无法 100% 还原 IE 的 GBK 名 - nginx + php-fpm 环境下,确认
client_max_body_size和upload_max_filesize都已调大,否则大文件上传会静默截断,$_FILES为空
$_FILES['name'] 为空或乱码的快速排查点
不是代码逻辑问题,而是基础配置或前端行为异常。先看 $_FILES 整体结构是否完整,再定位具体字段。
- 检查表单是否有
enctype="multipart/form-data"—— 缺失则$_FILES恒为空数组 - 用
var_dump($_FILES)确认'error'值:0表示成功,1或2是超限,3是文件只有部分上传 -
'name'为空但'error' === 0?说明浏览器提交了空文件(比如选中又取消),此时应拒绝处理 - Apache 下开启
mod_rewrite并用了某些重写规则,可能意外截断 multipart body —— 临时关闭 rewrite 测试
原始文件名只是起点,真正可靠的是 $_FILES['tmp_name'] 指向的临时文件路径。所有校验和重命名操作,都应该基于这个临时文件内容展开,而不是信任 name 字段本身。



















