hash_file

Calculates the message digest of a file's contents using the chosen hashing algorithm.

Signature
hash_file(string $algo, string $filename, bool $binary = false, array $options = []): string|false
  • Added in PHP 5.1.2

Parameters

ParameterTypeDescription
$algostringName of the hashing algorithm, for example "sha256". See hash_algos() for the supported list.
$filenamestringLocation of the file to be hashed. Supports fopen() stream wrappers.
$binaryoptionalbool= falseWhen true, outputs raw binary data instead of lowercase hexits.
$optionsoptionalarray= []Algorithm-specific options. Currently only the "seed" key, used by the MurmurHash variants.

Return value

string|falseThe digest as lowercase hexits, the raw binary digest when binary is true, or false on failure.

Errors

Throws a ValueError if algo is unknown. A missing or unreadable file returns false and emits an E_WARNING.

Changelog

  • PHP 8.1.0The options parameter was added.
  • PHP 8.0.0An unknown algo now throws a ValueError; previously false was returned with an E_WARNING.

hash_file() streams a file through the chosen algorithm and returns its digest. Crucially it reads the file in chunks, so hashing a 4 GB archive uses a few kilobytes of memory — unlike hash($algo, file_get_contents($path)), which loads the whole thing first and will hit memory_limit.

When to reach for it

Use it to verify a download against a published checksum, to detect that a file on disk changed since you last saw it, to deduplicate uploads by content rather than filename, and to build content-addressed storage where the digest is the filename.

What trips people up

The two failure modes look different and both bite. An unknown algorithm throws a ValueError since PHP 8.0. A missing or unreadable file returns false and emits a warning — it does not throw. So a plain if (!$hash) check catches the file problem but not the algorithm typo, and a try/catch catches the typo but not the missing file. Handle both.

Because $filename goes through the stream layer, a path that arrives from user input can reach wrappers you did not intend. Resolve and validate paths before passing them in. And remember that the digest covers file contents only: renaming, moving or touching a file leaves its hash unchanged.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Verify a downloaded release archive against the sha256 checksum the vendor published.
  • Skip re-processing an uploaded file whose digest already exists in the database.
  • Detect tampering by comparing stored digests of config files against the files on disk.

Frequently asked questions

What is the difference between hash_file and hash(file_get_contents())?

They return the same digest, but hash_file() streams the file in chunks while file_get_contents() loads it entirely into memory. Use hash_file() for anything that might be large.

Does hash_file work on remote URLs?

It accepts any path the fopen() wrappers support, so http:// URLs work when allow_url_fopen is on. Never pass a user-supplied path straight through, since that lets a caller choose the wrapper.

Why does hash_file return false?

The file does not exist, is a directory, or cannot be read with the current permissions. An E_WARNING is emitted alongside the false return.

More examples

Verifying a published checksum

The first check passes; appending a single byte makes the second fail. hash_equals() is used rather than === because the published value may come from an untrusted channel.

Example · php
<?php
file_put_contents('release.tar', str_repeat('payload', 100));
$published = hash_file('sha256', 'release.tar');   // pretend this came from the vendor

$actual = hash_file('sha256', 'release.tar');
var_dump(hash_equals($published, $actual));

file_put_contents('release.tar', str_repeat('payload', 100) . 'x');
var_dump(hash_equals($published, hash_file('sha256', 'release.tar')));

unlink('release.tar');

Handling both failure modes

The three lines show the digest, the caught ValueError from a bad algorithm name, and the false return from a missing file — proving that the two error paths are genuinely different and both need handling.

Example · php
<?php
file_put_contents('a.txt', 'data');

function safeHash(string $algo, string $file): string {
    try {
        $h = hash_file($algo, $file);
    } catch (ValueError $e) {
        return 'bad algorithm';
    }
    return $h === false ? 'unreadable file' : $h;
}

echo safeHash('sha256', 'a.txt'), PHP_EOL;
echo safeHash('nope', 'a.txt'), PHP_EOL;
echo safeHash('sha256', 'nofile.txt'), PHP_EOL;
unlink('a.txt');

Discussion

  • Be the first to comment on this lesson.