如何在php中计算大文件的SHA256

如何在php中计算大文件的SHA256,php,hash,sha256,Php,Hash,Sha256,我想用PHP计算大文件的SHA256。目前,我正在使用Amazon Glacier存储旧文件及其API以上载存档。起初,我只是使用小文件,无法达到MB大小的图像。当我试图上传超过1MB的数据时,API回应说我给他们的校验和与他们计算的不同 以下是我上传文件的代码: //get the sha256 using the file path $image = //image path; $sha256 = hash_file("sha256", $image); $archive = $glaci

我想用PHP计算大文件的SHA256。目前,我正在使用Amazon Glacier存储旧文件及其API以上载存档。起初,我只是使用小文件,无法达到MB大小的图像。当我试图上传超过1MB的数据时,API回应说我给他们的校验和与他们计算的不同

以下是我上传文件的代码:

//get the sha256 using the file path
$image = //image path;
$sha256 = hash_file("sha256", $image);

$archive = $glacier->uploadArchive([
        'accountId' => '', 
        'body' => "",
        'checksum' => $sha256,
        'contentSHA256' => $sha256,
        'sourceFile' => $image,
        'vaultName' => 'my-vault'
    ]);
错误是:

AWS HTTP错误:客户端错误:`POSThttps://glacier.us-west-2.amazonaws.com/vaults/70/archives`导致“400错误请求”响应:{“代码”:“InvalidParameterValueException”,“消息”:“校验和不匹配:应为9F1D4DA29B6EC24ABDE48CB65CC32652F589467(截断…)

我尝试了下面的函数来检查最终的散列,但打印时它似乎不是正确的散列:

private function getFinalHash($file)
{
    $fp = fopen($file, "r");
    $ctx = hash_init('sha256');
    while (!feof($fp)) {
        $buffer = fgets($fp, 1024);
        hash_update($ctx, $buffer);
    }
    $hash = hash_final($ctx, true); print_r($hash);exit;
    fclose($fp);
}
结果散列如下所示:μM¢›n J½äŒ¨\195;&RÿX“gÖ”·IoA\C÷× 我认为这里唯一的问题是获取文件的最终哈希。文件大小为5.7MB


我认为提供校验和的正确方法有些问题,但我不知道如何处理大文件。我真的需要您的帮助。

设法获得所需的输出,并通过以下例程验证摘要

<?php
    $fileName = isset($argv[1]) ? $argv[1] : die("Usage : php sha256.php <<filename>> <<hash>>" . PHP_EOL);
    if(!file_exists($fileName))
        die("FATAL : The file specified does not exists!");

    $hash = isset($argv[2]) ? $argv[2] : die("Usage : php sha256.php <<filename>> <<hash>>" . PHP_EOL);

    $ctx = hash_init('sha256');

    echo("INFO : Reading file $fileName ...");
    $file = fopen($fileName, 'r');
    while(!feof($file)){
        $buffer = fgets($file, 1024);
        hash_update($ctx, $buffer);
    }
    echo(" DONE!" . PHP_EOL);

    echo("INFO : Calculating SHA256 hash of $fileName ...");
    $hashRaw = hash_final($ctx, false); // Here, set the $raw_output to false
    echo(" DONE!" . PHP_EOL);

    echo ($hash . " INPUT " . PHP_EOL);
    echo ($hashRaw . " OUTPUT " . PHP_EOL);

    if($hash == $hashRaw)
        echo("INFO : Hash Comparison: OK!" . PHP_EOL);
    else
        echo("WARN : Hash Comparison: MISMATCH!" . PHP_EOL);
    echo("END" . PHP_EOL);

这不是一个加密问题。您应该在stackoverflow上问这个问题。显然,您是以原始字节的形式发送校验和,而服务希望您以十六进制编码字符串的形式发送校验和。请查看hash_final中的第二个标志。对于hex而不是原始输出,将其设置为false。仅使用
hash_upda可能会重复吗te_stream()
而不是while循环?