登录
首页 >  文章 >  php教程

PHP上传文件夹方法及实现步骤

时间:2026-05-14 18:52:32 289浏览 收藏

PHP原生不支持文件夹上传,必须通过前端HTML5的webkitdirectory属性(仅Chromium和部分Firefox支持)触发多文件选择并手动构建含相对路径的FormData,后端再基于$_FILES二维数组逐个解析、严格校验文件名与路径(防止../遍历攻击)、安全还原目录结构并隔离存储;整个过程面临浏览器兼容性差、路径处理易出错、大文件夹并发写入不稳定等现实挑战,稍有疏忽便可能导致安全漏洞或数据混乱。

PHP上传文件夹_PHP实现文件夹上传方案

PHP原生不支持文件夹上传,必须依赖前端配合

浏览器的 <input type="file"> 默认不提供文件夹选择能力,HTML5 虽引入了 webkitdirectorydirectory 属性,但仅限 Chromium 系(Chrome、Edge)和 Firefox 部分版本,Safari 完全不支持。PHP 本身没有任何机制能“接收一个文件夹”,它只处理 HTTP POST 中的 $_FILES 数组——每个条目对应一个独立文件上传项。

前端需用 webkitdirectory 触发多文件递归读取

要让用户选中文件夹并上传其全部内容(含子目录),前端必须:

  • 使用 <input type="file" webkitdirectory="true" directory="true" multiple>
  • 监听 change 事件,遍历 event.target.files,注意:此时 FileList 是扁平化的,**不保留目录结构**;若需还原路径,必须用 file.webkitRelativePath(仅 Chromium 支持)
  • 对每个 File 构造 FormData,手动添加路径前缀(如 formData.append('files[]', file, file.webkitRelativePath || file.name)
  • 后端 PHP 才能通过 $_FILES['files']['name']$_FILES['files']['tmp_name'] 数组逐个处理

$_FILES 多文件上传时的数组结构容易误读

当用 multiple 上传 3 个文件时,$_FILES['files'] 不是普通数组,而是按字段维度组织的二维数组:

Array
(
    [name] => Array
        (
            [0] => a.txt
            [1] => sub/b.txt
            [2] => c.jpg
        )
    [tmp_name] => Array
        (
            [0] => /tmp/phpabc123
            [1] => /tmp/phpdef456
            [2] => /tmp/phpghi789
        )
)

正确遍历方式是:

for ($i = 0; $i < count($_FILES['files']['name']); $i++) {
    $originalName = $_FILES['files']['name'][$i];
    $tmpPath = $_FILES['files']['tmp_name'][$i];
    // 注意:$originalName 可能含路径(如 'sub/b.txt'),需用 basename() 提取文件名
    // 若需还原目录结构,应先解析 $originalName 得到相对路径,再拼到目标目录
}

服务端保存时路径处理不当会导致覆盖或越界

直接用 move_uploaded_file($tmpPath, '/var/www/uploads/' . basename($originalName)) 会丢失层级,所有文件都挤在根目录。更危险的是,若用户伪造 originalName../../etc/passwd,可能触发路径遍历。安全做法是:

  • pathinfo($originalName, PATHINFO_DIRNAME) 解析相对路径,但**必须校验该路径不含 ..**
  • str_replace(['\\', '..'], '', $relativeDir) 或正则清除非法字符(更推荐 realpath() + 白名单根目录比对)
  • 目标存储路径应基于唯一上传 ID 构建,例如:/var/www/uploads/20240520_abc123/sub/b.txt
  • 确保上传目录有写权限,且 Web 服务器无法直接执行其中的 PHP 文件(可配合 .htaccess 或 Nginx location ~ \.php$ { deny all; }

真正难的不是上传动作本身,而是路径解析的健壮性、跨浏览器兼容性补丁、以及大文件夹下成百上千文件的并发写入稳定性——这些细节没压测过,上线就容易出问题。

以上就是《PHP上传文件夹方法及实现步骤》的详细内容,更多关于的资料请关注golang学习网公众号!

资料下载
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>