初学者学php文件上传怎么做_初学者学php文件上传实现【功能】

8次阅读

php文件上传必须检查$_FILES数组结构,其键名需与html表单name属性一致,仅$_FILES’field’可用于move_uploaded_file(),且须校验Error、size、真实MIME、扩展名白名单,并配置好目录权限与Web服务器解析策略。

初学者学php文件上传怎么做_初学者学php文件上传实现【功能】

PHP 文件上传必须检查 $_FILES 数组结构

PHP 上传文件后,所有元信息都存在 $_FILES 中,不是 $_POST$_GET。初学者常直接读 $_POST['file'],结果永远为空。

一个标准的 提交后,$_FILES 会是这样的结构:

Array (     [avatar] => Array         (             [name] => photo.jpg             [type] => image/jpeg             [tmp_name] => /tmp/phpABC123             [error] => 0             [size] => 204800         ) )

注意:键名 avatar 必须和 HTML 表单中 name 属性完全一致;[tmp_name] 是唯一能用于移动文件的临时路径;[error] 为 0 才表示上传成功。

  • [error] 值非 0 时(如 1 表示超 upload_max_filesize),不能调用 move_uploaded_file()
  • [tmp_name] 只在当前请求生命周期有效,下一次请求就失效
  • 多文件上传时(name="files[]"),$_FILES['files'] 是按字段维度组织的二维数组,不是按文件顺序

move_uploaded_file() 而不是 copy()rename()

move_uploaded_file() 是 PHP 唯一安全处理上传文件的函数。它内部做了校验:只允许从 $_FILES[...]['tmp_name'] 移动,拒绝任何伪造路径或本地文件。

立即学习PHP免费学习笔记(深入)”;

错误写法示例(危险):

$source = $_POST['fake_path']; // 攻击者可控制 rename($source, '/var/www/uploads/hacked.php');

正确做法必须基于 $_FILEStmp_name

$uploadDir = '/var/www/uploads/'; $uploadFile = $uploadDir . basename($_FILES['avatar']['name']); if ($_FILES['avatar']['error'] === 0) {     if (move_uploaded_file($_FILES['avatar']['tmp_name'], $uploadFile)) {         echo "上传成功";     } }
  • 目标路径必须提前创建好目录并确保 Web 进程有写权限(如 chmod 755 uploads/
  • basename() 防止路径遍历(如 ../../etc/passwd),但不能替代后缀校验
  • 不要拼接用户传来的原始 name 直接入库或执行,可能含恶意字符或空格

绕过前端限制?后端必须重验文件类型和大小

HTML 的 accept="image/*"js 校验全可被绕过。攻击者能用 curlpostman 或改写 form 直接发任意文件。

关键校验点:

  • $_FILES['file']['size'] 对比 ini_get('upload_max_filesize') 和业务上限(如不能超 2MB)
  • 不要信 $_FILES['file']['type']浏览器提供,可伪造),要用 finfo_open(FILEINFO_MIME_TYPE) 检测真实 MIME
  • 检查扩展名需白名单(如 in_array(strtolower(pathinfo($name, PATHINFO_EXTENSION)), ['jpg', 'png', 'gif'])),不能只过滤 .php
  • 上传目录禁止解析 PHP(apache 需配置 php_flag engine offnginxlocation ~ .php$ { deny all; }

常见报错 undefined index: fileFailed to open stream: No such file

这两个错误基本指向同一个原因:表单没设对 enctype

HTML 表单必须显式声明:

漏掉 enctype="multipart/form-data",PHP 就不会解析上传字段,$_FILES 为空,$_FILES['file'] 自然报 Undefined index;后续 move_uploaded_file()tmp_name 为空,就会报 No such file

其他排查点:

  • 确认 php.inifile_uploads = On
  • 检查 post_max_sizeupload_max_filesize(否则大文件连 POST 都截断)
  • 上传字段 name 大小写要和 PHP 中读取的一致($_FILES['File']$_FILES['file']

实际部署时,最易忽略的是上传目录的权限与 Web 服务器解析策略——哪怕代码逻辑全对,放错目录或没关 PHP 解析,一张图片就能变成后门。

text=ZqhQzanResources