Überprüfen Sie, ob zwei Dateien mit reinem PHP identisch sind.

8

TL; DR: Ich habe ein CMS-System, das Anhänge (undurchsichtige Dateien) unter Verwendung von SHA-1 des Dateiinhalts als Dateiname speichert. Wie kann ich überprüfen, ob die hochgeladene Datei wirklich mit einer im Speicher übereinstimmt, da ich bereits weiß, dass der SHA-1-Hash für beide Dateien übereinstimmt? Ich hätte gerne eine hohe Leistung.

Lange Version:

Wenn ein Benutzer eine neue Datei auf das System hochlädt, berechne ich den SHA-1-Hash des hochgeladenen Dateiinhalts und überprüfe dann, ob eine Datei mit identischem Hash bereits im Speicher-Backend existiert. PHP stellt die hochgeladene Datei in /tmp , bevor mein Code ausgeführt wird, und dann führe ich sha1sum gegen die hochgeladene Datei aus, um SHA-1-Hash des Dateiinhalts zu erhalten. Ich berechne dann Fanout aus dem berechneten SHA-1-Hash und entscheide das Speicherverzeichnis unter der NFS-Verzeichnishierarchie. (Wenn beispielsweise der SHA-1-Hash für einen Dateiinhalt 37aefc1e145992f2cc16fabadcfe23eede5fb094 ist, lautet der permanente Dateiname /nfs/data/files/37/ae/fc1e145992f2cc16fabadcfe23eede5fb094 .) Zusätzlich zum Speichern des eigentlichen Dateiinhalts, habe ich INSERT eine neue Zeile in eine SQL-Datenbank für die Benutzer übermittelte Metadaten (zB Content-Type , Originaldateiname, Datumsstempel, usw.).

Der Eckfall, den ich gerade herausfinde, ist der Fall, in dem eine neu hochgeladene Datei SHA-1-Hash hat, der mit dem vorhandenen Hash im Speicher-Backend übereinstimmt. Ich weiß, dass die Veränderungen durch Zufall zufällig astronomisch niedrig sind, aber ich möchte sicher sein. (Für den Fall der Fälle siehe Ссылка )

Wie können Sie bei zwei Dateinamen $file_a und $file_b schnell prüfen, ob beide Dateien den gleichen Inhalt haben? Nehmen Sie an, dass Dateien zu groß sind, um in den Speicher geladen zu werden. Mit Python würde ich filecmp.cmp() verwenden, aber PHP scheint nichts Ähnliches zu haben. Ich weiß, dass dies mit fread() gemacht werden kann und abgebrochen wird, wenn ein nicht übereinstimmendes Byte gefunden wird, aber ich möchte diesen Code lieber nicht schreiben.

    
Mikko Rantalainen 17.09.2013, 12:31
quelle

5 Antworten

11

Wenn Sie bereits eine SHA1-Summe haben, können Sie einfach Folgendes tun:

%Vor%

sonst

%Vor%

Überprüfen Sie auch die Dateigröße, um eine Hash-Kollision etwas zu verhindern (was bereits sehr unwahrscheinlich ist). Auch mit MD5, weil es deutlich schneller ist als die SHA-Algorithmen (aber ein bisschen weniger einzigartig).

Aktualisierung:

So können Sie zwei Dateien genau vergleichen.

%Vor%     
Cobra_Fast 17.09.2013, 12:58
quelle
4

Aktualisieren

Wenn Sie sicherstellen wollen, dass die Dateien gleich sind, sollten Sie zuerst die Dateigrößen überprüfen und wenn sie übereinstimmen, dann differentieren Sie den Dateiinhalt. Dies ist viel schneller als eine Hash-Funktion und wird definitiv das richtige Ergebnis geben.

Es ist nicht erforderlich, den gesamten Dateiinhalt in den Speicher zu laden, wenn Sie den Inhalt mit md5_file() oder sha1_file() oder einer anderen hash_function überprüfen. Hier kommt ein Beispiel mit md5 :

%Vor%

Ausgabe:

%Vor%

In Ihrem Beispiel wäre es:

%Vor%

Wenn Sie eine Hash-Funktion verwenden, haben Sie immer eine Situation, in der Sie sich einerseits zwischen der Komplexität einerseits und der Wahrscheinlichkeit von Kollisionen andererseits entscheiden müssen (was bedeutet, dass zwei verschiedene Nachrichten den gleichen Hash erzeugen) .

    
hek2mgl 17.09.2013 12:33
quelle
1

Benutze Sha1 Hash, genau wie du es tust. Wenn sie gleich sind, vergleichen Sie ihre MD5-Hashs und Dateigröße auch. Wenn du dann eine Datei findest, die in allen 3 Prüfungen übereinstimmt, aber NICHT gleich ist - du hast gerade den heiligen Gral gefunden: D

    
dognose 17.09.2013 12:51
quelle
0

Wenn Ihre Dateien groß und binär sind, können Sie einige Bytes davon mit ein paar Offsets testen. Es sollte viel schneller als jede Hashing-Funktion sein, insbesondere, dass die Funktion das Ergebnis durch das erste andere Zeichen zurückgibt.

Diese Methode funktioniert jedoch nicht für Dateien mit nur wenigen unterschiedlichen Zeichen. Es ist das beste für große Archive, Videos und so weiter.

%Vor%     
sliwhas 17.09.2013 13:19
quelle
-2

Der folgende Code hilft Ihnen zu überprüfen, ob die Dateien identisch sind oder nicht.

%Vor%     
SwR 28.10.2013 09:53
quelle
yii\base\ErrorException
Copied! Copy Stacktrace Search Stackoverflow Search Google Error

PHP Core Warningyii\base\ErrorException

PHP Startup: Unable to load dynamic library 'mongodb.so' (tried: /usr/lib64/php/modules/mongodb.so (/usr/lib64/php/modules/mongodb.so: cannot open shared object file: No such file or directory), /usr/lib64/php/modules/mongodb.so.so (/usr/lib64/php/modules/mongodb.so.so: cannot open shared object file: No such file or directory))

$_GET = [
    'id' => '351595',
    'url' => 'verifying-that-two-files-are-identical-using-pure-php',
];

$_SESSION = [
    '__flash' => [],
];