首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 遞迴遍歷目錄完整實作:打造簡易檔案瀏覽器

     編輯:PHP 綜合知識

前言

目錄遍歷是 PHP 檔案系統操作的基礎技能。本文透過一個可互動的「簡易檔案瀏覽器」範例,示範如何結合 `opendir`、`readdir`、`chdir`、`getcwd` 等原生函式,實現目錄的遞迴瀏覽與上下層導航。程式碼採用 GET 傳遞 Base64 編碼路徑,適合教學或輕量級後台檔案管理雛形。

核心函式速查

函式用途
isset()檢查 `$_GET['id']` 是否存在
base64_decode()還原 URL 傳遞的路徑字串
chdir()切換當前工作目錄
opendir('.')開啟當前目錄資料流
readdir()逐一讀取目錄項目
is_dir()判斷是否為目錄
getcwd()取得當前絕對路徑
strrpos()尋找最後一個路徑分隔符,用於計算上層路徑

完整程式碼(單檔版)

<?php
// 6.php - 簡易目錄瀏覽器
if (isset($_GET['id'])) {
    // 還原路徑:將空格還原為 +,再 Base64 解碼
    $s = str_replace(' ', '+', $_GET['id']);
    $s = base64_decode($s);
    chdir($s); // 切換到目標目錄
}

$handle = opendir('.'); // 開啟當前目錄

while (false !== ($entry = readdir($handle))) {
    // 略過 . 與 .. 的特殊處理放在後面
    if (is_dir($entry)) {
        if ($entry === '.') {
            // 當前目錄不顯示連結
            continue;
        } elseif ($entry === '..') {
            // 上一層目錄:取得父目錄路徑
            $current = getcwd();
            $parent = substr($current, 0, strrpos($current, '\\'));
            $encoded = base64_encode($parent);
            echo "上一級 <a href='6.php?id=$encoded'>打開</a><br />";
        } else {
            // 子目錄:組合絕對路徑並編碼
            $fullPath = getcwd() . '\\' . $entry;
            $encoded = base64_encode($fullPath);
            echo "$entry <a href='6.php?id=$encoded'>打開</a><br />";
        }
    } else {
        // 一般檔案
        echo "$entry 不是目錄<br />";
    }
}
closedir($handle);
?>

關鍵邏輯解析

1. 路徑編碼與解碼

URL 傳遞路徑時,直接使用中文或特殊字元會導致解析錯誤。範例採用 base64_encode() 將絕對路徑編碼為安全字串,前端連結攜帶 `id` 參數;後端以 str_replace(' ', '+') 修正 Base64 中 `+` 被 URL 解析為空格的問題,再 base64_decode() 還原。

2. 目錄切換與上下層導航

  • chdir($path) 讓後續 `opendir('.')` 作用於目標目錄。
  • 上一層(`..`)利用 strrpos(getcwd(), '\\') 找到最後一個反斜線,截取父路徑。
  • 子目錄直接用 getcwd() . '\\' . $entry 組合完整路徑。

3. Windows 與 Linux 路徑分隔符差異

範例使用反斜線 `\`,適用於 Windows 環境。若部署於 Linux,請將所有 `\` 改為 `/`,或使用常數 `DIRECTORY_SEPARATOR` 寫成跨平台相容代碼:

$parent = substr($current, 0, strrpos($current, DIRECTORY_SEPARATOR));
$fullPath = getcwd() . DIRECTORY_SEPARATOR . $entry;

安全性提醒 ⚠️

  • 路徑遍歷風險:使用者可透過竄改 `id` 參數存取伺服器任意目錄。實務上必須加入路徑白名單驗證(如限制在 `/var/www/data` 之下)。
  • 權限控管:生產環境務必搭配登入驗證與角色授權,避免敏感檔案洩露。
  • 輸出轉義:檔名直接輸出至 HTML,應使用 `htmlspecialchars()` 防止 XSS。

進階擴充方向

  1. 加入檔案大小、修改時間、權限顯示(`filesize`、`filemtime`、`fileperms`)。
  2. 支援檔案下載、刪除、重新命名、新建資料夾等操作。
  3. 前端改用 AJAX + JSON 打造類桌面體驗的檔案管理器(參考 TinyFileManager、FileGator 等開源專案)。
  4. 使用 `RecursiveDirectoryIterator` + `RecursiveIteratorIterator` 實現真正的遞迴遍歷(SPL 標準庫,更優雅)。

SPL 現代寫法對比

<?php
$root = isset($_GET['path']) ? base64_decode(str_replace(' ', '+', $_GET['path'])) : __DIR__;
$root = realpath($root); // 規範化路徑,防止遍歷攻擊

$iterator = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($root, RecursiveDirectoryIterator::SKIP_DOTS),
    RecursiveIteratorIterator::SELF_FIRST
);

foreach ($iterator as $file) {
    $relative = substr($file->getPathname(), strlen($root) + 1);
    $encoded = base64_encode($file->getPathname());
    $icon = $file->isDir() ? '📁' : '📄';
    echo "$icon $relative <a href='?path=$encoded'>開啟</a><br>";
}
?>

SPL 版本自動處理遞迴、略過 `.` `..`、跨平台路徑,程式碼更簡潔且效能更好,建議新專案優先採用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved