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

PHP 判斷目錄/檔案讀寫權限的實用方法與遞迴檢查

     編輯:PHP 相關知識

前言

在產生靜態檔案、上傳目錄、快取目錄等場景,必須確認目錄是否可寫。is_writable() 僅能檢查單一檔案/目錄,且受限於 Web 伺服器執行身分(通常為 www-data、nobody)。本文提供「建立測試檔」法判斷目錄寫入權限,並延伸至遞迴檢查子目錄與檔案的完整方案。

基礎:is_writable() 限制

$filename = 'test.txt';
if (is_writable($filename)) {
    echo '可寫入';
} else {
    echo '不可寫入';
}

缺點:目錄必須存在且為實體檔案/目錄;無法檢查「空目錄」是否可建立檔案。

核心邏輯:在目錄建立暫存檔測試

若能在目錄成功 fopen(..., 'w') 建立檔案並寫入,即代表有寫入權限。測試完畢立即 fclose() + unlink() 清理。

遞迴檢查函式:check_dir_iswritable($dir_path)

function check_dir_iswritable($dir_path) {
    // 正規化路徑分隔符
    $dir_path = str_replace('\\', '/', $dir_path);
    
    // 1. 確認是目錄且存在
    if (!is_dir($dir_path)) return 0;

    // 2. 嘗試在當前目錄建立測試檔
    $testFile = $dir_path . '/.write_test_' . uniqid();
    $fp = @fopen($testFile, 'w');
    if (!$fp) return 0;
    fclose($fp);
    @unlink($testFile);

    // 3. 掃描子項目
    $dh = opendir($dir_path);
    while (($item = readdir($dh)) !== false) {
        if ($item === '.' || $item === '..') continue;
        $fullPath = $dir_path . '/' . $item;
        
        if (is_file($fullPath)) {
            // 檔案:直接檢查 is_writable
            if (!is_writable($fullPath)) return 0;
        } elseif (is_dir($fullPath)) {
            // 子目錄:遞迴檢查(同樣用建立測試檔法)
            $subTest = $fullPath . '/.write_test_' . uniqid();
            $fp2 = @fopen($subTest, 'w');
            if (!$fp2) return 0;
            fclose($fp2);
            @unlink($subTest);
            
            // 遞迴
            if (!check_dir_iswritable($fullPath)) return 0;
        }
    }
    closedir($dh);
    return 1; // 全部可寫
}

使用範例

set_time_limit(1000); // 避免深層目錄超時
$targetDir = '/var/www/html/uploads';
if (check_dir_iswritable($targetDir)) {
    echo "目錄 $targetDir 及所有子項目皆可寫入 ✅";
} else {
    echo "目錄 $targetDir 存在不可寫入項目 ❌";
}

關鍵細節與改進建議

  • 測試檔名唯一化:使用 uniqid() 避免並發衝突。
  • 錯誤抑制 @:僅用於 fopen/unlink 避免警告干擾流程,正式環境建議改用 try-catch + 例外處理。
  • 權限位元檢查:Linux 下可搭配 fileperms() 檢查 0755/0775 等權限位元,但實際能否寫入仍取決於進程擁有者與 ACL,故「實測建檔」最可靠。
  • 效能考量:深層大目錄遞迴較慢,建議僅在部署腳本、安裝精靈、後台健康檢查等低頻場景使用;高頻 API 請改用快取機制(如 Redis 記錄檢查結果)。
  • Windows 注意:Windows 無執行位元概念,is_writable 僅檢查 ACL,實測建檔法同樣適用。

總結

「實測建立暫存檔」是判斷目錄可寫性最可靠的方法。封裝為遞迴函式並搭配唯一測試檔名、錯誤抑制、資源釋放,即可構建健壯的權限檢查工具,適用於靜態頁生成、檔案上傳、快取目錄驗證等核心場景。

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