Ich habe diese und diese Fragen , die , dass die Datei MIME - Typ vorzuschlagen scheint Javascript überprüft werden könnte unter Verwendung auf Client - Seite. Jetzt verstehe ich, dass die eigentliche Validierung noch auf der Serverseite durchgeführt werden muss. Ich möchte eine clientseitige Überprüfung durchführen, um unnötige Verschwendung von Serverressourcen zu vermeiden.
Um zu testen, ob dies auf der Clientseite möglich ist, habe ich die Erweiterung einer JPEG
Testdatei in geändert .png
und die Datei zum Hochladen ausgewählt. Vor dem Senden der Datei frage ich das Dateiobjekt mit einer Javascript-Konsole ab:
document.getElementsByTagName('input')[0].files[0];
Folgendes bekomme ich auf Chrome 28.0:
Datei {webkitRelativePath: "", lastModifiedDate: Di 16.10.2012 10:00:00 GMT + 0000 (UTC), Name: "test.png", Typ: "image / png", Größe: 500055…}
Es wird der Typ image/png
angezeigt, der darauf hinweist, dass die Überprüfung basierend auf der Dateierweiterung anstelle des MIME-Typs erfolgt. Ich habe Firefox 22.0 ausprobiert und es gibt mir das gleiche Ergebnis. Gemäß der W3C-Spezifikation sollte MIME Sniffing implementiert werden.
Kann ich zu Recht sagen, dass es derzeit keine Möglichkeit gibt, den MIME-Typ mit Javascript zu überprüfen? Oder fehlt mir etwas?
quelle
I want to perform a client side checking to avoid unnecessary wastage of server resource.
Ich verstehe nicht, warum Sie sagen, dass die Validierung auf der Serverseite durchgeführt werden muss, aber dann sagen Sie, dass Sie die Serverressourcen reduzieren möchten. Goldene Regel: Vertraue niemals Benutzereingaben . Was bringt es, den MIME-Typ auf der Clientseite zu überprüfen, wenn Sie dies dann nur auf der Serverseite tun? Sicherlich ist das eine "unnötige Verschwendung von Kundenressourcen "?type
Eigenschaft fürFile
Objekte einfach auf die Dateierweiterungen . Der Webkit-Quellcode zum Beispiel enthüllt diese Wahrheit. Es ist möglich, Dateien clientseitig genau zu identifizieren, indem unter anderem in den Dateien nach "magischen Bytes" gesucht wird. Ich arbeite derzeit an einer MIT-Bibliothek (in der wenigen Freizeit, die ich habe), die genau das tun wird. Wenn Sie an meinen Fortschritten interessiert sind, besuchen Sie github.com/rnicholus/determinater .image/jpeg
, und Sie haben dies nicht durch Ändern der Erweiterung geändert?Antworten:
Sie können den MIME-Dateityp einfach mit JavaScript ermitteln,
FileReader
bevor Sie ihn auf einen Server hochladen. Ich bin damit einverstanden, dass wir die serverseitige Überprüfung der clientseitigen Überprüfung vorziehen sollten, aber die clientseitige Überprüfung ist weiterhin möglich. Ich werde Ihnen zeigen, wie und unten eine funktionierende Demo bereitstellen.Überprüfen Sie, ob Ihr Browser sowohl
File
als auch unterstütztBlob
. Alle wichtigen sollten.Schritt 1:
Sie können die
File
Informationen von einem<input>
Element wie diesem abrufen ( ref ):Hier ist eine Drag-and-Drop-Version des oben genannten ( ref ):
Schritt 2:
Wir können jetzt die Dateien überprüfen und Header und MIME-Typen herausziehen.
✘ Schnelle Methode
Sie können Blob naiv nach dem MIME-Typ der Datei fragen, die er darstellt, indem Sie dieses Muster verwenden:
Bei Bildern werden MIME-Typen wie folgt zurückgegeben:
Vorsichtsmaßnahme: Der MIME-Typ wird anhand der Dateierweiterung erkannt und kann getäuscht oder gefälscht werden. Man kann a
.jpg
in a umbenennen.png
und der MIME-Typ wird als gemeldetimage/png
.✓ Richtige Methode zur Überprüfung des Headers
Um den bonafide MIME-Typ einer clientseitigen Datei zu erhalten, können wir einen Schritt weiter gehen und die ersten Bytes der angegebenen Datei untersuchen, um sie mit sogenannten magischen Zahlen zu vergleichen . Seien Sie gewarnt, dass es nicht ganz einfach ist, zum Beispiel JPEG einige "magische Zahlen" enthält. Dies liegt daran, dass sich das Format seit 1991 weiterentwickelt hat. Möglicherweise müssen Sie nur die ersten beiden Bytes überprüfen, aber ich bevorzuge es, mindestens 4 Bytes zu überprüfen, um Fehlalarme zu reduzieren.
Beispiel für Dateisignaturen von JPEG (erste 4 Bytes):
Hier ist der wesentliche Code zum Abrufen des Dateikopfs:
Sie können dann den tatsächlichen MIME-Typ wie folgt bestimmen (weitere Dateisignaturen hier und hier ):
Akzeptieren oder lehnen Sie das Hochladen von Dateien nach Ihren Wünschen ab, basierend auf den erwarteten MIME-Typen.
Demo
Hier ist eine funktionierende Demo für lokale Dateien und Remote-Dateien (ich musste CORS nur für diese Demo umgehen). Öffnen Sie das Snippet, führen Sie es aus, und es sollten drei Remote-Images verschiedener Typen angezeigt werden. Oben können Sie ein lokales Bild oder eine lokale Datendatei auswählen. Die Dateisignatur und / oder der MIME-Typ werden angezeigt.
Beachten Sie, dass selbst wenn ein Bild umbenannt wird, sein wahrer MIME-Typ bestimmt werden kann. Siehe unten.
Bildschirmfoto
Code-Snippet anzeigen
quelle
fileReader.readAsArrayBuffer(blob.slice(0,4))
? (2) Sollte der Header zum Kopieren / Einfügen von Dateisignaturen nicht mit führenden Nullen erstellt werdenfor(var i = 0; i < bytes.length; i++) { var byte = bytes[i]; fileSignature += (byte < 10 ? "0" : "") + byte.toString(16); }
?FF D8 FF E2
= CANNON EOS JPEG-DATEI,FF D8 FF E3
= SAMSUNG D500 JPEG-DATEI. Der Hauptteil der JPEG-Signatur besteht nur aus 2 Bytes. Um jedoch Fehlalarme zu reduzieren, habe ich die häufigsten 4-Byte-Signaturen hinzugefügt. Ich hoffe das hilft.fileReader.readAsArrayBuffer(blob.slice(0, 4))
Wie in anderen Antworten angegeben, können Sie den MIME-Typ überprüfen, indem Sie die Signatur der Datei in den ersten Bytes der Datei überprüfen .
Andere Antworten laden jedoch die gesamte Datei in den Speicher , um die Signatur zu überprüfen. Dies ist sehr verschwenderisch und kann Ihren Browser leicht einfrieren, wenn Sie versehentlich eine große Datei auswählen oder nicht.
quelle
readyState
wird immerFileReader.DONE
im Event-Handler ( W3C-Spezifikation ) sein, auch wenn es einen Fehler gab - sollte die Prüfung nicht(!e.target.error)
stattdessen erfolgen?Für alle, die dies nicht selbst implementieren möchten, hat Sindresorhus ein Dienstprogramm erstellt, das im Browser funktioniert und die Header-to-Mime-Zuordnungen für die meisten gewünschten Dokumente enthält.
https://github.com/sindresorhus/file-type
Sie können den Vorschlag von Vitim.us kombinieren, nur die ersten X Bytes zu lesen, um zu vermeiden, dass mit diesem Dienstprogramm alles in den Speicher geladen wird (Beispiel in es6):
quelle
"file-type": "12.4.0"
funktionierte und ich mussteimport * as fileType from "file-type";
Wenn Sie nur überprüfen möchten, ob es sich bei der hochgeladenen Datei um ein Bild handelt, können Sie einfach versuchen, es in das
<img>
Tag zu laden und nach Fehlern zu suchen.Beispiel:
quelle
Das müssen Sie tun
Wenn Sie nach Bilddateitypen suchen möchten, dann
quelle
Hier ist eine Typescript-Implementierung, die webp unterstützt. Dies basiert auf der JavaScript-Antwort von Vitim.us.
quelle
Wie Drake feststellt, könnte dies mit FileReader geschehen. Was ich hier jedoch präsentiere, ist eine funktionale Version. Beachten Sie, dass das große Problem bei der Verwendung von JavaScript darin besteht, die Eingabedatei zurückzusetzen. Nun, dies beschränkt sich nur auf JPG (für andere Formate müssen Sie den MIME-Typ und die magische Zahl ändern ):
Beachten Sie, dass dies auf den neuesten Versionen von Firefox und Chrome sowie auf IExplore 10 getestet wurde.
Eine vollständige Liste der MIME-Typen finden Sie in Wikipedia .
Eine vollständige Liste der magischen Zahlen finden Sie in Wikipedia .
quelle
Hier ist eine Erweiterung der Antwort von Roberto14, die Folgendes bewirkt:
Dies erlaubt nur Bilder
Überprüft, ob FileReader verfügbar ist, und greift auf die Erweiterungsprüfung zurück, wenn diese nicht verfügbar ist.
Gibt eine Fehlermeldung aus, wenn kein Bild vorhanden ist
Wenn es sich um ein Bild handelt, wird eine Vorschau geladen
** Sie sollten weiterhin eine serverseitige Validierung durchführen. Dies ist für den Endbenutzer vor allem eine Annehmlichkeit. Aber es ist praktisch!
quelle
Kurze Antwort ist nein.
Wie Sie bemerken, leiten sich die Browser
type
von der Dateierweiterung ab. Die Mac-Vorschau scheint auch über die Erweiterung zu laufen. Ich gehe davon aus, dass es schneller ist, den im Zeiger enthaltenen Dateinamen zu lesen, als die Datei auf der Festplatte nachzuschlagen und zu lesen.Ich habe eine Kopie eines mit png umbenannten JPG erstellt.
Ich konnte aus beiden Bildern in Chrom konsistent Folgendes erhalten (sollte in modernen Browsern funktionieren).
ÿØÿàJFIFÿþ;CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), quality = 90
Womit Sie eine String.indexOf ('jpeg') - Prüfung auf Bildtyp durchführen könnten.
Hier ist eine Geige zum Erkunden von http://jsfiddle.net/bamboo/jkZ2v/1/
Die mehrdeutige Zeile habe ich im Beispiel vergessen zu kommentieren
console.log( /^(.*)$/m.exec(window.atob( image.src.split(',')[1] )) );
Der Geigencode verwendet die Base64-Dekodierung, die in IE9 nicht funktioniert. Ich habe ein schönes Beispiel mit einem VB-Skript gefunden, das in IE funktioniert Http://blog.nihilogic.dk/2008/08/imageinfo-reading-image-metadata-with.html
Der Code zum Laden des Bildes stammt von Joel Vardy, der vor dem Hochladen eine coole Seite für die Größenänderung von Bildern erstellt, die von Interesse sein kann. Https://joelvardy.com/writing/javascript-image-upload
quelle
JFIF
stattdessen nach einer Suche suchen , müssen Sie auchAPP0
kein JFIF in EXIF-JPEGs enthalten , damit es auch nicht funktioniert).