Я хотел бы попросить вашей помощи в том, как вычислить sha256 больших файлов в PHP. В настоящее время я использую Amazon Glacier для хранения старых файлов и использую их API для загрузки архива. Первоначально я просто использовал небольшие файлы, которые не могут достигать изображений размером в МБ. Когда я попытался загрузить более 1 МБ, в ответе 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 error: Client error: `POST https://glacier.us-west-2.amazonaws.com/vaults/70/archives` resulted in a `400 Bad Request` response:{"code":"InvalidParameterValueException","message":"Checksum mismatch: expected 9f1d4da29b6ec24abde48cb65cc32652ff589467 (truncated...)
Я попробовал функцию, как показано ниже, чтобы проверить окончательный хеш, но кажется, что это не правильный хэш, когда я его печатаю:
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½äŒ¶\Ã&RÿX”gíÖ'„IoA\C÷×
В документации Amazon Glacier API показано, как вычислить контрольную сумму, как указано:
Для каждого фрагмента данных полезной нагрузки размером 1 МБ вычислите хэш SHA-256. Последний блок данных может быть меньше 1 МБ. Например, если вы загружаете архив размером 3,2 МБ, вы вычисляете хэш-значения SHA-256 для каждого из первых трех фрагментов данных размером 1 МБ, а затем вычисляете хэш SHA-256 оставшихся данных размером 0,2 МБ. Эти хеш-значения образуют листовые узлы дерева.
Я думаю, что есть что-то в правильном способе предоставления контрольной суммы, но я не знаю, как мне это сделать с большими файлами с использованием PHP. Мне очень нужна ваша помощь в этом вопросе.
length
в байтах, а не в килобайтах. То есть вы пропускаете не 1 мб, а 1 кб. Вы должны умножить его на 1024, чтобы получить фрагмент размером 1 МБ, но это вам не сильно поможет, поскольку fgets читает файл, пока не достигнетlength
или новой строки. Поэтому, если вы используетеfgets()
для файла размером 1,2 МБ, вы, вероятно, получите гораздо больше, чем 2 фрагмента, если в этом файле много строк. - person SzymonM   schedule 27.03.2017checksum
— это хеш-дерево с размером блока 1 МиБ, аcontentSHA256
— линейный хэш, но вы передаете$sha256
для обоих. Эти два значения не могут быть идентичными, если только размер файла не превышает 1 МиБ. - person Michael - sqlbot   schedule 27.03.2017