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

PHP unlink 刪除檔案權限判斷與安全實踐完整指南

     編輯:PHP 相關知識

基本用法

unlink($file) or die("無法刪除檔案: $file");

返回 `true` 成功,`false` 失敗(權限不足、檔案不存在、被鎖定等)。

常見失敗原因:目錄權限而非檔案權限

刪除檔案實際是修改**目錄項目**,需對**所在目錄**擁有寫入(`w`)與執行(`x`)權限,而非檔案本身。

例如:`/var/www/uploads/photo.jpg` 屬於 `www-data:www-data` 644,目錄 `/var/www/uploads` 屬於 `root:root` 755。PHP 以 `www-data` 執行,無法在目錄中刪除項目 → 失敗。

刪除前權限檢查函數

function canDeleteFile(string $path): bool {
    if (!file_exists($path)) return false;
    if (!is_file($path)) return false; // 目錄需用 rmdir

    $dir = dirname($path);
    // 檢查目錄是否可寫(隱含執行權限)
    if (!is_writable($dir)) return false;

    // 額外:檢查檔案本身是否可寫(某些系統需檔案 w 權限才能 unlink)
    if (!is_writable($path)) return false;

    return true;
}

// 使用
if (canDeleteFile($file)) {
    unlink($file);
} else {
    error_log("刪除失敗:權限不足 $file");
}

is_readable / is_writable 注意事項

  • PHP 以 Web Server 使用者(如 `www-data`、`nobody`、`apache`)身份執行,權限判斷基於該使用者。
  • 安全模式(已棄用)或 open_basedir 限制會影響結果。
  • Windows 下 `is_writable` 僅檢查唯讀屬性,ACL 需用 `icacls` 或 COM 物件檢查。

完整刪除流程範例(含編碼轉換、日誌)

function safeDelete(string $filepath): bool {
    // 1. 路徑編碼統一(Windows 中文路徑常見問題)
    $filepath = iconv('UTF-8', 'GBK//IGNORE', $filepath); // 視伺服器編碼調整

    // 2. 存在性
    if (!file_exists($filepath)) {
        trigger_error("檔案不存在: $filepath", E_USER_WARNING);
        return false;
    }

    // 3. 權限
    if (!is_writable(dirname($filepath)) || !is_writable($filepath)) {
        trigger_error("權限不足無法刪除: $filepath", E_USER_WARNING);
        return false;
    }

    // 4. 執行刪除
    $result = @unlink($filepath);
    if (!$result) {
        trigger_error("unlink 執行失敗: $filepath", E_USER_ERROR);
    }
    return $result;
}

進階:刪除整個目錄樹(遞迴)

function rrmdir(string $dir): bool {
    if (!is_dir($dir)) return false;
    $items = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
        RecursiveIteratorIterator::CHILD_FIRST
    );
    foreach ($items as $item) {
        $item->isDir() ? rmdir($item->getPathname()) : unlink($item->getPathname());
    }
    return rmdir($dir);
}

最佳實踐清單

  1. **最小權限原則**:上傳目錄僅授予 PHP 使用者 `rwx`,其他目錄嚴禁寫入。
  2. **路徑驗證**:刪除前用 `realpath()` 解析絕對路徑,確保在允許範圍內(防止目錄遍歷 `../../etc/passwd`)。
  3. **日誌記錄**:所有刪除操作記錄 `用戶、時間、檔案、結果`,便於審計。
  4. **軟刪除優先**:重要資料改為 `is_deleted=1` 或移至回收站目錄,定期清理。
  5. **異步處理**:大量刪除放入隊列,避免阻塞請求。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved