Hash update stream: примеры (PHP)
hash_update_stream(HashContext $context, resource $stream, int $length = -1): intФункция hash_update_stream() является частью модуля Hash в PHP и предназначена для инкрементального обновления контекста хеширования данными из потока. Она позволяет обрабатывать большие файлы или данные, не загружая их полностью в память.
Использование функции актуально при работе с крупными файлами, когда требуется вычислить хеш-сумму без чтения всего файла в память. Также функция применяется в ситуациях, когда данные поступают постепенно из потока ввода-вывода.
Аргументы функции:
- context (ресурс) — контекст хеширования, созданный функцией
hash_init(). Обязательный аргумент. - handle (ресурс) — открытый поток (например, возвращаемый функцией
fopen()). Обязательный аргумент. - length (int) — максимальное количество данных для чтения из потока в байтах. По умолчанию
-1, что означает чтение до конца потока.
Функция возвращает true в случае успеха или false при возникновении ошибки.
<?php
$context = hash_init('sha256');
$handle = fopen('large_file.txt', 'rb');
hash_update_stream($context, $handle);
$hash = hash_final($context);
echo $hash;
fclose($handle);
?>a1b2c3d4e5f6789012345678901234567890123456789012345678901234567890
<?php
$context = hash_init('md5');
$handle = fopen('data.txt', 'rb');
// Чтение только первых 1024 байт
hash_update_stream($context, $handle, 1024);
$hash = hash_final($context);
echo $hash;
fclose($handle);
?>098f6bcd4621d373cade4e832627b4f6
- hash_update() — обновляет контекст хеширования строкой данных. Подходит для работы с данными в виде строк, а не потоков.
- hash_file() — вычисляет хеш файла напрямую. Удобна для простых случаев, когда не требуется инкрементальная обработка.
- hash_init() + hash_final() — базовые функции для инкрементального хеширования.
hash_update_stream()дополняет их для работы с потоками.
Выбор функции зависит от источника данных: hash_update_stream() оптимальна для потоков, hash_file() — для файлов целиком, hash_update() — для строк.
Hash update stream в Python
Модуль hashlib позволяет инкрементальное хеширование через методы update(), принимающие байты. Потоки обрабатываются чтением блоками.
import hashlib
sha256 = hashlib.sha256()
with open('large_file.txt', 'rb') as f:
for chunk in iter(lambda: f.read(4096), b''):
sha256.update(chunk)
print(sha256.hexdigest())a1b2c3d4e5f6789012345678901234567890123456789012345678901234567890
Модуль crypto предоставляет потоковые трансформы. Метод update() может принимать данные чанками.
const crypto = require('crypto');
const fs = require('fs');
const hash = crypto.createHash('sha256');
const stream = fs.createReadStream('large_file.txt');
stream.on('data', chunk => hash.update(chunk));
stream.on('end', () => console.log(hash.digest('hex')));a1b2c3d4e5f6789012345678901234567890123456789012345678901234567890
Hash update stream в MySQL
Функции SHA2() или MD5() вычисляют хеш для строки, но не поддерживают инкрементальную обработку потоков. Для файлов требуется чтение средствами языка приложения.
<?php
$context = hash_init('sha256');
$handle = 'not_a_stream';
// Вызовет предупреждение
hash_update_stream($context, $handle);
?>Warning: hash_update_stream() expects parameter 2 to be resource, string given
<?php
$context = hash_init('sha256');
$handle = fopen('file.txt', 'rb');
fclose($handle);
// Поток уже закрыт
hash_update_stream($context, $handle);
?>Warning: hash_update_stream(): supplied resource is not a valid stream resource
<?php
$handle = fopen('file.txt', 'rb');
// Контекст не создан
hash_update_stream(null, $handle);
?>Warning: hash_update_stream() expects parameter 1 to be resource, null given
Начиная с PHP 8.0, функция выбрасывает исключение Error в случае неверного количества аргументов. Ранее это вызывало предупреждение.
В PHP 8.1 не было значительных изменений в поведении функции. Однако улучшена общая обработка ресурсов, что может повлиять на сообщения об ошибках.
<?php
$context = hash_init('sha3-512');
$file1 = fopen('part1.bin', 'rb');
$file2 = fopen('part2.bin', 'rb');
hash_update_stream($context, $file1);
hash_update_stream($context, $file2);
$hash = hash_final($context);
echo "Общий хеш: $hash";
fclose($file1);
fclose($file2);
?>Общий хеш: 9a3b... (хеш конкатенации двух файлов)
<?php
// Хеширование тела HTTP-запроса
$context = hash_init('sha256');
$input = fopen('php://input', 'rb');
hash_update_stream($context, $input);
$hash = hash_final($context);
header('X-Request-Hash: ' . $hash);
?>HTTP-заголовок X-Request-Hash содержит хеш тела запроса
<?php
$context = hash_init('crc32b');
$source = fopen('source.iso', 'rb');
$dest = fopen('copy.iso', 'wb');
while (!feof($source)) {
$buffer = fread($source, 8192);
fwrite($dest, $buffer);
// Обновление хеша прочитанным блоком
hash_update($context, $buffer);
}
$hash = hash_final($context);
echo "Хеш при копировании: $hash";
fclose($source);
fclose($dest);
?>Хеш при копировании: 12345678
<?php
$context = hash_init('md5');
$remote = fopen('http://example.com/large.zip', 'rb', false, stream_context_create([]));
hash_update_stream($context, $remote, 1048576); // Только первые 1 МБ
$hash = hash_final($context);
echo "Хеш первых мегабайт: $hash";
fclose($remote);
?>Хеш первых мегабайт: 5d41402abc4b2a76b9719d911017c592