當前位置: 首頁> 最新文章列表> 使用md5_file() 和數據庫管理文件簽名表

使用md5_file() 和數據庫管理文件簽名表

M66 2025-06-05

在開發涉及文件管理、版本控製或文件完整性驗證的系統時,構建一個高效的文件簽名表非常關鍵。 PHP 提供了內置函數md5_file()來計算文件的MD5 散列值,我們可以結合數據庫實現一個靈活且高效的文件簽名系統。本文將帶你一步步實現這個目標。

一、為什麼選擇md5_file()

md5_file()是PHP 提供的一個便捷函數,用於計算文件內容的MD5 值。與md5()不同的是,它不需要你先用file_get_contents()讀取整個文件,而是直接通過文件路徑計算簽名,這在處理大文件時更高效。

示例用法:

 $hash = md5_file('/path/to/file.zip');
echo $hash;

二、數據庫結構設計

為了管理文件簽名,我們需要在數據庫中記錄以下信息:

  • 文件路徑或唯一標識

  • 文件的MD5 值

  • 更新時間戳

一個簡單的MySQL 表結構可以如下:

 CREATE TABLE file_hashes (
    id INT AUTO_INCREMENT PRIMARY KEY,
    file_path VARCHAR(255) NOT NULL UNIQUE,
    md5_hash CHAR(32) NOT NULL,
    updated_at DATETIME NOT NULL
);

三、實現文件簽名更新與校驗邏輯

我們可以通過定期掃描文件目錄,比較當前文件的MD5 值與數據庫中存儲的值,判斷文件是否發生了變化。

 function updateFileHash($filePath, $pdo) {
    if (!file_exists($filePath)) {
        return false;
    }

    $md5 = md5_file($filePath);
    $now = date('Y-m-d H:i:s');

    $stmt = $pdo->prepare("SELECT md5_hash FROM file_hashes WHERE file_path = :file_path");
    $stmt->execute(['file_path' => $filePath]);
    $existing = $stmt->fetch(PDO::FETCH_ASSOC);

    if ($existing) {
        if ($existing['md5_hash'] !== $md5) {
            // 文件內容已更改,更新記錄
            $updateStmt = $pdo->prepare("
                UPDATE file_hashes 
                SET md5_hash = :md5_hash, updated_at = :updated_at 
                WHERE file_path = :file_path
            ");
            $updateStmt->execute([
                'md5_hash' => $md5,
                'updated_at' => $now,
                'file_path' => $filePath
            ]);
        }
    } else {
        // 新文件,插入記錄
        $insertStmt = $pdo->prepare("
            INSERT INTO file_hashes (file_path, md5_hash, updated_at) 
            VALUES (:file_path, :md5_hash, :updated_at)
        ");
        $insertStmt->execute([
            'file_path' => $filePath,
            'md5_hash' => $md5,
            'updated_at' => $now
        ]);
    }

    return true;
}

四、批量掃描目錄並更新簽名表

可以通過遍歷文件系統,對目錄下的文件進行批量簽名管理:

 function scanDirectoryAndUpdate($directory, $pdo) {
    $files = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($directory)
    );

    foreach ($files as $file) {
        if ($file->isFile()) {
            updateFileHash($file->getPathname(), $pdo);
        }
    }
}

五、典型應用場景

這種機制可廣泛應用於:

  • 文件版本追踪系統

  • CDN 或緩存失效判斷

  • 防篡改監控系統

  • 簡易部署系統的文件同步檢測

例如,部署系統可以在上傳文件前先計算其MD5 值,與服務器端數據庫中的記錄進行比對,如果一致就無需上傳,提升部署效率。

你甚至可以構建一個Web 面板來查看文件簽名變化歷史,類似: