You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让PHP文件管理器实现递归访问,无需在各目录放置index文件

实现单文件PHP目录浏览器

问题

我正在用PHP开发一款文件资源管理器,现在得在每个文件夹里都放个index.php才能访问对应目录。怎么实现动态/递归功能,只用单个index.php就能访问所有目录?

原代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>M07</title>
</head>
<body>

    <?php

        $contingut = "";

        if($handle = opendir('.')){
            while (false !== ($file = readdir($handle))){

                if (($file != ".") && ($file != "..") && ($file != "index.php") && ($file != "desktop.ini")){

                    $contingut .= '<a id="enllaç" href="'.$file.'">'.$file.'</a><br><br>';
                }
            }
            closedir($handle);
        }
?>
<?php echo $contingut ?>

解决方案

核心是通过URL参数传递当前访问目录,用单个index.php处理所有请求,无需在每个目录放置文件。以下是修改后的实现:

1. 安全的动态目录处理代码

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>文件资源管理器</title>
    <style>
        .file-item { margin: 8px 0; }
        .folder { color: #2c3e50; font-weight: bold; }
        .back-btn { margin-bottom: 16px; padding: 4px 8px; }
    </style>
</head>
<body>
    <?php
    // 定义允许访问的根目录(必须是绝对路径,防止目录遍历)
    $rootDir = __DIR__;
    // 获取用户请求的目录,默认是根目录
    $currentDir = isset($_GET['dir']) ? $_GET['dir'] : '';
    
    // 安全校验:防止目录遍历漏洞,确保请求的目录在根目录范围内
    $targetDir = realpath($rootDir . DIRECTORY_SEPARATOR . $currentDir);
    if (!$targetDir || strpos($targetDir, $rootDir) !== 0) {
        die('非法访问:禁止访问该目录');
    }

    $content = '';

    // 添加返回上一级按钮(如果不在根目录)
    if ($targetDir !== $rootDir) {
        $parentDir = dirname($currentDir);
        $content .= '<a href="?dir=' . urlencode($parentDir) . '" class="back-btn">← 返回上一级</a><br>';
    }

    // 遍历当前目录
    if ($handle = opendir($targetDir)) {
        while (false !== ($file = readdir($handle))) {
            if ($file === "." || $file === ".." || $file === "desktop.ini") {
                continue;
            }

            $filePath = $targetDir . DIRECTORY_SEPARATOR . $file;
            $relativePath = $currentDir ? $currentDir . DIRECTORY_SEPARATOR . $file : $file;
            $url = is_dir($filePath) ? '?dir=' . urlencode($relativePath) : $relativePath;
            
            // 区分文件夹和文件的样式
            $class = is_dir($filePath) ? 'folder' : 'file';
            $content .= '<div class="file-item"><a href="' . htmlspecialchars($url) . '" class="' . $class . '">' . htmlspecialchars($file) . '</a></div>';
        }
        closedir($handle);
    } else {
        $content .= '<p>无法访问该目录</p>';
    }
    ?>
    <?php echo $content ?>
</body>
</html>

2. 关键改进点

  • 目录安全控制:用realpath()和字符串校验确保用户只能访问$rootDir范围内的目录,彻底防范目录遍历攻击(比如?dir=../../etc这类恶意请求)
  • 动态目录传递:通过?dir=xxx参数传递当前访问的目录路径,点击文件夹时自动拼接该参数
  • 用户体验优化:添加返回上一级按钮,区分文件夹和文件样式
  • 安全输出:用htmlspecialchars()转义输出内容,防止XSS攻击

3. 服务器配置(可选,优化URL美观度)

如果想让URL更友好(比如/files/docs而不是/?dir=docs),可以配置服务器重写规则:

Apache(.htaccess)

在根目录创建.htaccess文件:

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?dir=$1 [QSA,L]
Nginx

在站点配置中添加:

location / {
    try_files $uri $uri/ /index.php?dir=$uri;
}

注意事项

  • 确保PHP进程对目标目录有读取权限,否则无法遍历文件
  • 不要随意放开$rootDir范围,严格限制可访问的目录
  • 可以根据需求添加文件下载、排序、搜索等扩展功能

内容的提问来源于stack exchange,提问作者Imad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 09:35:33