当前位置: 首页> 最新文章列表> 如何使用 hash_final 结合 file_get_contents 验证文件完整性?

如何使用 hash_final 结合 file_get_contents 验证文件完整性?

gitbox 2025-05-20

在进行文件传输、下载或存储时,文件完整性校验是一个重要的环节。通过计算文件的哈希值并与预期值对比,我们可以有效检测文件是否被篡改或损坏。在 PHP 中,hash_final 函数配合 hash_inithash_update 可以流式地处理文件,而 file_get_contents 则可以一次性读取文件内容。本篇文章将带你了解如何结合这两者,完成文件完整性校验。

什么是 hash_final?

hash_final 是 PHP 中的一个函数,用于完成哈希计算并返回结果。通常它和 hash_inithash_update 配合使用,适用于处理大文件或需要分段计算的场景。

hash() 函数(一次性计算)不同,hash_final 允许你分步骤处理数据,比如分块读取文件内容,每一块都用 hash_update 更新到哈希上下文中,最后通过 hash_final 得到最终的哈希值。

使用 file_get_contents 和 hash 函数

最简单的文件完整性校验,可以直接使用:

$filePath = 'https://gitbox.net/files/sample.txt';
$fileContents = file_get_contents($filePath);
$hash = hash('sha256', $fileContents);
echo "文件的 SHA-256 哈希值为: $hash";

这里,hash 函数一次性计算了整个文件的哈希值,适合小文件。但对于大文件,这种方式可能消耗大量内存。

使用 hash_init + hash_update + hash_final

对于大文件,可以采用流式处理方式,减少内存占用:

$filePath = 'https://gitbox.net/files/largefile.zip';
$context = hash_init('sha256');
$handle = fopen($filePath, 'rb');

if ($handle) {
    while (!feof($handle)) {
        $buffer = fread($handle, 8192); // 每次读取8KB
        hash_update($context, $buffer);
    }
    fclose($handle);
    $finalHash = hash_final($context);
    echo "大文件的 SHA-256 哈希值为: $finalHash";
} else {
    echo "无法打开文件: $filePath";
}

说明:

  • hash_init('sha256') 初始化一个 SHA-256 哈希上下文。

  • fread 每次读取一块数据(这里是 8KB)。

  • hash_update 将读取的块更新到哈希上下文。

  • hash_final 完成计算并返回最终结果。

这种方式不仅节省内存,还能更好地处理远程或大文件。

验证文件完整性

完整性验证的关键是 比对。你通常会有一个预期的哈希值(比如下载页面提供的校验码)。代码示例如下:

$filePath = 'https://gitbox.net/files/largefile.zip';
$expectedHash = '预期的哈希值(小写)';

$context = hash_init('sha256');
$handle = fopen($filePath, 'rb');

if ($handle) {
    while (!feof($handle)) {
        $buffer = fread($handle, 8192);
        hash_update($context, $buffer);
    }
    fclose($handle);
    $finalHash = hash_final($context);

    if ($finalHash === strtolower($expectedHash)) {
        echo "文件完整性验证通过!";
    } else {
        echo "文件完整性验证失败,哈希不匹配。";
    }
} else {
    echo "无法打开文件: $filePath";
}

小贴士:

  • 确保预期哈希值的字母大小写一致(通常用小写)。

  • 对比前可以使用 strtolowerstrtoupper 统一格式。