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

PHP DirectoryIterator 打造動態下拉式檔案選單

     編輯:PHP 相關知識

需要讓使用者從伺服器目錄中選擇檔案?PHP 的 DirectoryIterator (SPL) 提供物件導向、記憶體友善的目錄遍歷方式,輕鬆產生 <select> 選單。本文示範完整實作,並說明過濾、排序、安全性等實務細節。

基本範例:列出指定目錄所有檔案

<?php
$targetDir = __DIR__ . '/uploads'; // 絕對路徑更安全

if (!is_dir($targetDir)) {
    die("目錄不存在: $targetDir");
}

echo '<select name="file">';
echo '<option value="">-- 請選擇檔案 --</option>';

$iterator = new DirectoryIterator($targetDir);
foreach ($iterator as $fileInfo) {
    // 跳過 . 、.. 、隱藏檔、目錄
    if ($fileInfo->isDot() || $fileInfo->isDir() || $fileInfo->getFilename()[0] === '.') {
        continue;
    }

    $filename = $fileInfo->getFilename();
    // htmlentities 防 XSS,value 用原始檔名
    echo '<option value="' . htmlentities($filename, ENT_QUOTES, 'UTF-8') . '">'
       . htmlentities($filename, ENT_QUOTES, 'UTF-8')
       . '</option>';
}
echo '</select>';
?>

進階:遞歸列出子目錄、依類型分組、排序

<?php
function buildFileSelect(string $dir, string $name = 'file', array $options = []): string
{
    $defaults = [
        'recursive'      => false,   // 是否遞歸子目錄
        'show_dirs'      => false,   // 是否包含目錄
        'extensions'     => null,    // 允許副檔名陣列 ['php','txt'],null=全部
        'sort_by'        => 'name',  // name|size|time
        'sort_order'     => 'asc',   // asc|desc
        'include_path'   => false,   // value 是否包含相對路徑
        'placeholder'    => '-- 請選擇 --',
    ];
    $opt = array_merge($defaults, $options);

    if (!is_dir($dir)) return '<!-- 目錄不存在 -->';

    $iterator = $opt['recursive']
        ? new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS))
        : new DirectoryIterator($dir);

    $files = [];
    foreach ($iterator as $info) {
        if (!$info->isFile() && !$opt['show_dirs']) continue;
        if ($info->isDir() && !$opt['show_dirs']) continue;

        $filename = $info->getFilename();
        if ($opt['extensions'] && !in_array(strtolower($info->getExtension()), $opt['extensions'])) continue;

        $relPath = $opt['include_path']
            ? $info->getPathname()
            : $filename;

        $files[] = [
            'name'  => $filename,
            'path'  => $relPath,
            'size'  => $info->getSize(),
            'mtime' => $info->getMTime(),
        ];
    }

    // 排序
    $sortKey = $opt['sort_by'];
    $order = $opt['sort_order'] === 'desc' ? -1 : 1;
    usort($files, fn($a, $b) => $order * strcmp($a[$sortKey], $b[$sortKey]));

    // 產生 HTML
    $html = '<select name="' . htmlentities($name) . '">';
    if ($opt['placeholder']) {
        $html .= '<option value="">' . htmlentities($opt['placeholder']) . '</option>';
    }
    foreach ($files as $f) {
        $html .= '<option value="' . htmlentities($f['path']) . '">'
               . htmlentities($f['name']) . '</option>';
    }
    $html .= '</select>';

    return $html;
}

// 使用範例
echo buildFileSelect(__DIR__ . '/templates', 'template', [
    'recursive'   => true,
    'extensions'  => ['php', 'html', 'twig'],
    'sort_by'     => 'mtime',
    'sort_order'  => 'desc',
    'include_path'=> true,
]);
?>

關鍵方法速查表

方法說明
getFilename()取得檔名(含副檔名)
getBasename($suffix)取得檔名,可選移除副檔名
getExtension()取得副檔名(不含點)
getPathname()取得完整路徑
getPath()取得所在目錄路徑
isFile() / isDir() / isLink()類型判斷
isDot()是否為 . 或 ..
isReadable() / isWritable()權限檢查
getSize()檔案大小(位元組)
getMTime() / getATime() / getCTime()修改/存取/建立時間(Unix 時間戳)
getPerms()權限位元遮罩

安全性必做三件事

  1. 路徑限制:絕對禁止直接使用使用者輸入的路徑。必須將使用者選擇的檔名與預設基礎目錄拼接,並用 realpath() 驗證結果仍在基礎目錄下(防止目錄遍歷攻擊 ../../etc/passwd)。
  2. 輸出編碼:檔名輸出到 HTML 時,務必用 htmlentities() 防 XSS。
  3. 副檔名白名單:若後續會執行/包含該檔案,嚴格限制允許的副檔名。

效能提示

  • DirectoryIterator 逐一載入,記憶體穩定,適合大量檔案目錄。
  • 避免在迴圈中重複呼叫 getPathname() 等方法,若需多次使用請先存變數。
  • 超大目錄(萬檔以上)建議快取選單 HTML,或改用 AJAX 分頁載入。

掌握 DirectoryIterator,不只能做下拉選單,更是建構檔案管理器、圖片庫、程式碼編輯器等功能的基石。

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