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