PHP文件管理器问题:无法打开Start文件夹子目录下的文件
问题分析与解决方案
先直接说核心问题:你点击子文件夹里的文件时页面回到Start文件夹,根源是点击文件按钮提交表单时,没有携带当前的工作目录(cwd)参数,导致服务器端认为未设置cwd,直接重置回初始的Start路径。
具体原因拆解
看你的代码逻辑:
- 当用户点击文件按钮时,表单只提交了
name='file'的参数,$_POST['cwd']是空的。 - 服务器端的判断
if(!isset($_POST['cwd']))触发,把$directory重置为getcwd() . DIRECTORY_SEPARATOR . $start,也就是回到了初始的Start文件夹。 - 另外,你把读取文件内容的逻辑放在了目录遍历的循环里,这会导致每次页面加载(哪怕只是进入文件夹)都会执行文件读取,逻辑顺序完全错误。
修复步骤
1. 在表单中添加隐藏字段保存当前cwd
修改面包屑部分的表单代码,加入一个隐藏字段携带当前目录,这样点击文件按钮时,表单会同时提交file和cwd参数:
echo "<form method='post' id='ch_cwd'>"; // 添加隐藏字段保存当前工作目录 echo "<input type='hidden' name='cwd' value='" . htmlspecialchars($directory) . "'>"; echo "</form>";
2. 调整文件内容处理逻辑的位置
把读取和输出文件内容的代码移到目录遍历之前,并且只在用户点击文件按钮时执行:
// 先处理文件请求,放在目录遍历前 if(isset($_POST['file'])){ $filename = $_POST['file']; // 安全验证:确保文件在Start目录范围内,防止目录遍历攻击 $startPath = realpath(getcwd() . DIRECTORY_SEPARATOR . $start); $fileRealPath = realpath($filename); if($fileRealPath && str_starts_with($fileRealPath, $startPath)){ if(file_exists($filename)){ $ressource = fopen($filename, 'rb'); echo fread($ressource, filesize($filename)); fclose($ressource); // 记得关闭文件资源 } } else { echo "无权访问该文件!"; } } // 再进行目录遍历和渲染按钮 $dir = scandir($directory); foreach( $dir as $item){ if($item !== "." && $item !== ".."){ if($item[0] === "."){ continue; // 直接跳过隐藏文件,比echo空字符串更简洁 } elseif(is_dir($directory . DIRECTORY_SEPARATOR . $item)){ echo "<button type='submit' name='cwd' form='ch_cwd' value='" . htmlspecialchars($directory . DIRECTORY_SEPARATOR . $item) . "' class='d-inline-block pr-4'> " . "<i class='fas fa-folder-open fa-4x pt-2 pb-2 pr-2 text-primary'></i>". htmlspecialchars($item) . "</button>"; } else{ echo "<button type='submit' name='file' form='ch_cwd' value='" . htmlspecialchars($directory . DIRECTORY_SEPARATOR . $item) . "' class='d-inline-block pr-4'> " . "<i class='fas fa-file fa-4x pt-2 pb-2 pr-2 text-primary'></i>". htmlspecialchars($item) . "</button>"; } } }
3. 额外的安全提示
直接使用$_POST里的路径参数非常危险,容易被利用进行目录遍历攻击(比如用户提交../../etc/passwd这类恶意路径)。上面的修复代码里加入了realpath和str_starts_with的验证,确保用户只能访问Start文件夹及其子目录下的文件,一定要保留这个验证!
其他小优化
- 遍历目录时遇到隐藏文件,用
continue跳过比echo ""更简洁高效。 - 输出HTML属性值时,用
htmlspecialchars()转义,防止XSS攻击。 - 打开文件后记得用
fclose()关闭资源,避免内存泄漏。
这样修改后,点击子文件夹里的文件时,表单会携带当前的cwd参数,服务器端就不会重置目录,同时文件内容的处理逻辑也会正确触发啦!
内容的提问来源于stack exchange,提问作者Lisa El Yacoubi
相关产品推荐
相关产品推荐

