In PHP, md5_file() is a very useful function used to calculate the MD5 hash value of a specified file's content. Its basic syntax is as follows:
md5_file(string $filename, bool $binary = false): string|false
This function is commonly used in file validation, caching mechanisms, file integrity checks, and other scenarios. However, developers may encounter a confusing problem during usage: the file exists, the path is correct, but md5_file() returns false. This is usually due to a file permission issue. This article will explain the reasons, common situations, and solutions in detail.
md5_file() tries to read the entire file content internally to perform the MD5 calculation. Therefore, if the PHP script doesn't have sufficient permissions to read the target file, the function will return false.
For md5_file() to work, the file must have "readable permission". This includes the following aspects:
The file itself must be readable by the current executing user (e.g., www-data).
All parent directories must have "execute permission" (i.e., they must be "enterable") so PHP can access the path.
System security modules like SELinux, AppArmor, etc., may also affect access permissions.
When the file permission is set to 600 (read-write for the owner), if the PHP executing user is not the file's owner, the file cannot be read.
-rw------- 1 root root 1024 May 28 10:00 secret.txt
If PHP is running as the www-data user, it will not be able to read the file above, and md5_file() will fail.
Even if the file itself has read permission, if the directory does not allow PHP to enter, the file cannot be accessed.
drwx------ 2 user user 4096 May 28 10:00 /var/private/
In this case, even if the file is set to 644, PHP will not be able to access /var/private/secret.txt.
Some Linux systems have SELinux or AppArmor enabled. Even if file permissions appear "normal," they may be restricted by system policies.
You can check SELinux restrictions with the following command:
ls -Z /path/to/file
Ensure that the target file has read permission for the PHP user. The simplest way is to set the file permission to 644 and ensure that the PHP user has permission for the directory as well:
chmod 644 /path/to/file.txt
chown www-data:www-data /path/to/file.txt
You can temporarily debug the current executing user with the following PHP code:
echo get_current_user(); // Or use posix_geteuid()
Ensure that the user has permission to access the target file and directory.
Before calling md5_file(), first check if the file is readable to avoid errors:
$file = '/var/data/file.txt';
if (is_readable($file)) {
$hash = md5_file($file);
echo "Hash: $hash";
} else {
echo "File is not readable, please check permissions";
}
If you're on a system with SELinux enabled, you may need to change the context with the chcon command:
chcon -t httpd_sys_content_t /path/to/file.txt
Alternatively, you can temporarily disable SELinux for testing (not recommended for production environments):
setenforce 0
If you are using a CDN or a remote address like https://m66.net/files/check.txt, md5_file() will also fail. This function only works with local file paths and cannot handle URLs. You can first download the remote file and then process it as follows:
error_reporting = E_ALL
display_errors = On