Suma kontrolna pliku w PHP na przykładzie md5

W ostatnim czasie tworzyłem skrypt, który musiał badać sumy kontrolne plików i porównywać je z gotową listą – po prostu weryfikacja, czy pliki są oby na pewno w porządku, z użyciem hashy md5. Wszystko byłoby bardzo proste, gdyby nie fakt, że pliki bywały dosyć spore (nawet ponad 250 MB), a nie miałem żadnego wpływu na ustawienia z php.ini. Dlaczego o tym wspominam? Ano dlatego, że pierwsze co przyszło na myśl to użycie funkcji md5_file. W sieci można znaleźć również inne specyficzne rozwiązanie tj. wczytanie zawartości pliku, a następnie obliczenie przy pomocy funkcji md5() hasha dla tych danych:

$checksum = md5(file_get_contents($filename));

Niestety przy sporych plikach momentalnie przekraczamy limit zajętej pamięci, bo przecież ich zawartość leci właśnie tam. Takie rozwiązanie odpada. Lepszym wydawało się użycie wspomnianej funkcji md5_file, która pamięci nam tak nie zawala:

$checksum = md5_file($filename);

To niestety również nie było satysfakcjonującym wynikiem, bo o ile skrypt nie przekraczał limitu pamięci, o tyle często nie był w stanie wyrobić się z obliczeniem sumy w czasie jaki miał do dyspozycji (np. 60 sekund). Po prostu obliczenie sumy md5 za pośrednictwem PHP było za wolne. Kolejne rozwiązanie – sięgnięcie do shella:

$result = explode('= ',exec("openssl md5 $filename"));
$checksum = $result[1];

W tym wypadku obliczanie sumy kontrolnej trwało… ponad 3-4 razy krócej! Było to już więc całkiem niezłe rozwiązanie, oczywiście do pewnego rozmiaru. Okazało się jednak, że istnieje jeszcze szybsza metoda, skracająca ten czas jeszcze dwukrotnie, czasami nawet więcej. Zamiast używać openssl md5, można od razu użyć md5sum, dodatkowo z parametrem “b” tj. czytanie w trybie binarnym. Na koniec przedstawiam więc metodę, która w moim wypadku okazała się najszybsza, dodatkowo jest ona “skompletowana” poprzez przefiltrowanie zmiennej która idzie do funkcji shell_exec:

$result = explode(' ', exec('md5sum -b ' . escapeshellarg($filename)));
$checksum = $result[0];

Warto zwrócić uwagę na różnicę w pierwszym argumencie dla explode oraz sam dostęp do elementu tablicy z sumą kontrolną – oba polecenia zwracają dane w nieco inny sposób (oraz kolejności). To by by było na tyle. Dlaczego nie SHA albo CRC? Pierwszy z nich okazał się sporo wolniejszy, drugi nie odbiegał od md5 ale zwracał sumy w formacie dwuczłonowym, a mi zależało na jak najszybszym i najkrótszym otrzymaniu sum kontrolnych. Jeżeli znacie metody lepsze / szybsze, lub też gdzieś popełniłem błąd, poprawcie mnie.