在無法配置 Nginx autoindex on 或 Apache Options +Indexes 的環境(如共享主機、臨時測試目錄),單個 PHP 文件即可實現目錄列表、文件類型識別、大小/時間顯示、文件下載、PHP 源碼高亮預覽。
<?php
// 安全:限制只能瀏覽當前目錄及子目錄,防止目錄遍歷攻擊
$baseDir = realpath(__DIR__);
$requestDir = isset($_GET['dir']) ? realpath($_GET['dir']) : $baseDir;
if ($requestDir === false || strpos($requestDir, $baseDir) !== 0) {
http_response_code(403);
die('Access Denied: Directory traversal attempt');
}
// 若是文件直接處理
if (is_file($requestDir)) {
// 圖片/文本直接輸出,PHP 源碼高亮
$ext = strtolower(pathinfo($requestDir, PATHINFO_EXTENSION));
if ($ext === 'php') {
highlight_file($requestDir);
} else {
header('Content-Type: ' . mime_content_type($requestDir));
readfile($requestDir);
}
exit;
}
// 目錄瀏覽
$it = new FilesystemIterator($requestDir, FilesystemIterator::SKIP_DOTS | FilesystemIterator::KEY_AS_PATHNAME);
?>
<!DOCTYPE html>
<html><head>
<meta charset="UTF-8">
<title>Directory Index: <?= htmlspecialchars($requestDir) ?></title>
<style>
body {font-family: monospace; margin: 20px; background: #fafafa;}
h1 {border-bottom: 1px solid #ddd; padding-bottom: 10px;}
table {width: 100%; border-collapse: collapse; background: white; box-shadow: 0 1px 3px rgba(0,0,0,.1);}
th, td {padding: 8px 12px; text-align: left; border-bottom: 1px solid #eee;}
th {background: #f5f5f5; position: sticky; top: 0;}
a {color: #0366d6; text-decoration: none;} a:hover {text-decoration: underline;}
.dir {font-weight: bold; color: #22863a;}
.size {text-align: right; color: #666; white-space: nowrap;}
.time {color: #666; white-space: nowrap;}
.parent {color: #cb2431;}
</style>
</head><body>
<h1>Directory: <?= htmlspecialchars($requestDir) ?></h1>
<table>
<thead><tr><th>Name</th><th class="time">Modified</th><th class="size">Size</th></tr></thead>
<tbody>
<?php if ($requestDir !== $baseDir): ?>
<tr><td colspan="3"><a class="parent" href="?dir=<?= urlencode(dirname($requestDir)) ?>">.. (Parent Directory)</a></td></tr>
<?php endif; ?>
<?php foreach ($it as $path => $file):
$name = $file->getFilename();
$isDir = $file->isDir();
$size = $isDir ? '-' : $file->getSize();
$time = date('Y-m-d H:i', $file->getMTime());
$url = '?dir=' . urlencode($path);
?>
<tr>
<td><a class="<?= $isDir ? 'dir' : '' ?>" href="<?= $url ?>"><?= htmlspecialchars($name) ?><?= $isDir ? '/' : '' ?></a></td>
<td class="time"><?= $time ?></td>
<td class="size"><?= $isDir ? '-' : formatSize($size) ?></td>
</tr>
<?php endforeach; ?>
</tbody></table>
</body></html>
<?php
function formatSize($bytes) {
$units = ['B','KB','MB','GB','TB'];
for ($i=0; $bytes>=1024 && $i<4; $i++) $bytes/=1024;
return round($bytes,2).' '.$units[$i];
}
?>
realpath + strpos($baseDir) === 0 確保不越界。highlight_file() 彩色高亮Content-Disposition: attachment)index.php 放入需瀏覽的目錄。index.php 設置為默認索引文件。?download=1 參數強制下載而非預覽。htaccess 密碼保護或 PHP 簡易認證限制訪問權限。