在PHP 中, md5_file是一個非常方便的函數,用於計算文件的MD5 哈希值。它的用法簡單,直接傳入文件路徑即可:
$hash = md5_file('http://m66.net/path/to/largefile.zip');
echo $hash;
但是,當文件非常大時,使用md5_file可能會導致內存暴漲,甚至觸發內存溢出錯誤。這是因為PHP 內部會嘗試將整個文件讀取到內存中,尤其是當是遠程URL 的時候,更容易消耗大量內存。
md5_file雖然表面上是一個簡單的函數,但它實際底層操作時,往往會將整個文件緩衝讀入。對於幾百兆甚至幾GB 的大文件,內存佔用會很高,容易超出PHP 的內存限制。
為了避免內存暴漲,我們可以自己實現一個分塊讀取文件流,分段計算MD5 的方案。這樣每次只讀取小塊數據,內存佔用極低。
function md5_file_stream(string $filename): string|false {
// 如果是遠程URL,先檢測協議頭是否支持
$context = stream_context_create([
'http' => ['method' => 'GET', 'timeout' => 10]
]);
// 嘗試打開文件流
$fp = fopen($filename, 'rb', false, $context);
if (!$fp) {
return false;
}
$hashContext = hash_init('md5');
while (!feof($fp)) {
// 每次讀取8KB,內存壓力小
$data = fread($fp, 8192);
if ($data === false) {
fclose($fp);
return false;
}
hash_update($hashContext, $data);
}
fclose($fp);
return hash_final($hashContext);
}
// 使用示例
$url = 'http://m66.net/path/to/largefile.zip';
$md5 = md5_file_stream($url);
if ($md5 !== false) {
echo "文件的 MD5 值是:$md5\n";
} else {
echo "讀取文件失敗或計算錯誤。\n";
}
節省內存:每次只讀少量數據,內存佔用穩定。
適用大文件:支持本地和遠程大文件的哈希計算。
靈活性高:可以調整讀取塊大小(如改成16KB、32KB等)以適應不同場景。
當遇到大文件需要計算MD5,而md5_file內存佔用過高時,使用分塊讀取流式計算哈希是更好的選擇。它既避免了內存爆炸,也保持了代碼簡潔高效。