| 函數 | 用途 | 返回值 |
|---|---|---|
| unlink() | 刪除文件 | bool |
| opendir() | 打開目錄句柄 | resource|false |
| readdir() | 讀取目錄條目 | string|false |
| closedir() | 關閉目錄句柄 | void |
| is_dir() | 判斷是否目錄 | bool |
| pathinfo() | 解析路徑信息 | array |
| glob() | 模式匹配查找文件 | array |
<?php
function safeDeleteFile(string $filePath): bool {
// 1. 路徑規範化,防止目錄遍歷攻擊
$realPath = realpath($filePath);
$allowedRoot = realpath(__DIR__ . '/uploads');
if ($realPath === false || strpos($realPath, $allowedRoot) !== 0) {
error_log("非法刪除嘗試: $filePath");
return false;
}
// 2. 確認是文件且存在
if (!is_file($realPath)) {
return false;
}
// 3. 嘗試刪除
if (@unlink($realPath)) {
return true;
}
error_log("刪除失敗: $realPath");
return false;
}
// 使用
safeDeleteFile('uploads/temp/test.txt');
?>
<?php
function listFiles(string $dir): array {
$files = [];
if (!is_dir($dir)) return $files;
foreach (new DirectoryIterator($dir) as $fileInfo) {
if ($fileInfo->isDot()) continue; // 跳過 . 和 ..
if ($fileInfo->isFile()) {
$files[] = $fileInfo->getFilename();
}
}
return $files;
}
print_r(listFiles('message/'));
?>
<?php
function listFilesRecursive(string $dir): array {
$files = [];
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS)
);
foreach ($iterator as $fileInfo) {
if ($fileInfo->isFile()) {
// 獲取相對路徑
$files[] = $iterator->getSubPathname();
}
}
return $files;
}
?>
<?php
function getImageFiles(string $dir, array $extensions = ['jpg', 'jpeg', 'png', 'gif', 'webp']): array {
$images = [];
if (!is_dir($dir)) return $images;
// 使用 glob 模式匹配,效率高於遍歷判斷
$patterns = array_map(fn($ext) => "$dir/*.$ext", $extensions);
foreach ($patterns as $pattern) {
foreach (glob($pattern) as $file) {
if (is_file($file)) {
$images[] = basename($file);
}
}
}
// 自然排序
natsort($images);
return array_values($images);
}
// 使用
$images = getImageFiles('images/');
print_r($images);
// 輸出: Array ( [0] => banner1.jpg [1] => banner2.png [2] => logo.gif )
?>
<?php
function getFileDetails(string $dir): array {
$details = [];
foreach (new DirectoryIterator($dir) as $info) {
if ($info->isDot() || !$info->isFile()) continue;
$details[] = [
'name' => $info->getFilename(),
'path' => $info->getPathname(),
'size' => $info->getSize(), // 字節
'size_human'=> humanFileSize($info->getSize()),
'mime' => mime_content_type($info->getPathname()),
'mtime' => $info->getMTime(), // Unix 時間戳
'mtime_fmt' => date('Y-m-d H:i:s', $info->getMTime()),
'extension' => strtolower($info->getExtension()),
];
}
return $details;
}
function humanFileSize(int $bytes, int $decimals = 2): string {
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
$factor = floor((strlen($bytes) - 1) / 3);
return sprintf("%.{$decimals}f", $bytes / (1024 ** $factor)) . ' ' . $units[$factor];
}
?>
DirectoryIterator, GlobIterator):面向對象、自動資源管理、可組合過濾器。glob():底層 C 實現,比 PHP 迴圈快得多。realpath() 校驗是否在允許根目錄下。@unlink() 僅在確認文件存在時使用,否則會掩蓋權限、鎖定等真實問題。LimitIterator 分頁處理。掌握這些現代 PHP 文件系統 API,能編寫出更安全、高效、可維護的文件操作代碼。