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ützt Blob
. Alle wichtigen sollten.
if (window.FileReader && window.Blob) {
// All the File APIs are supported.
} else {
// File and Blob are not supported
}
Schritt 1:
Sie können die File
Informationen von einem <input>
Element wie diesem abrufen ( ref ):
<input type="file" id="your-files" multiple>
<script>
var control = document.getElementById("your-files");
control.addEventListener("change", function(event) {
// When the control has changed, there are new files
var files = control.files,
for (var i = 0; i < files.length; i++) {
console.log("Filename: " + files[i].name);
console.log("Type: " + files[i].type);
console.log("Size: " + files[i].size + " bytes");
}
}, false);
</script>
Hier ist eine Drag-and-Drop-Version des oben genannten ( ref ):
<div id="your-files"></div>
<script>
var target = document.getElementById("your-files");
target.addEventListener("dragover", function(event) {
event.preventDefault();
}, false);
target.addEventListener("drop", function(event) {
// Cancel default actions
event.preventDefault();
var files = event.dataTransfer.files,
for (var i = 0; i < files.length; i++) {
console.log("Filename: " + files[i].name);
console.log("Type: " + files[i].type);
console.log("Size: " + files[i].size + " bytes");
}
}, false);
</script>
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:
var blob = files[i]; // See step 1 above
console.log(blob.type);
Bei Bildern werden MIME-Typen wie folgt zurückgegeben:
image / jpeg
image / png
...
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 gemeldet image/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):
FF D8 FF E0 (SOI + ADD0)
FF D8 FF E1 (SOI + ADD1)
FF D8 FF E2 (SOI + ADD2)
Hier ist der wesentliche Code zum Abrufen des Dateikopfs:
var blob = files[i]; // See step 1 above
var fileReader = new FileReader();
fileReader.onloadend = function(e) {
var arr = (new Uint8Array(e.target.result)).subarray(0, 4);
var header = "";
for(var i = 0; i < arr.length; i++) {
header += arr[i].toString(16);
}
console.log(header);
// Check the file signature against known types
};
fileReader.readAsArrayBuffer(blob);
Sie können dann den tatsächlichen MIME-Typ wie folgt bestimmen (weitere Dateisignaturen hier und hier ):
switch (header) {
case "89504e47":
type = "image/png";
break;
case "47494638":
type = "image/gif";
break;
case "ffd8ffe0":
case "ffd8ffe1":
case "ffd8ffe2":
case "ffd8ffe3":
case "ffd8ffe8":
type = "image/jpeg";
break;
default:
type = "unknown"; // Or you can use the blob.type as fallback
break;
}
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
// Return the first few bytes of the file as a hex string
function getBLOBFileHeader(url, blob, callback) {
var fileReader = new FileReader();
fileReader.onloadend = function(e) {
var arr = (new Uint8Array(e.target.result)).subarray(0, 4);
var header = "";
for (var i = 0; i < arr.length; i++) {
header += arr[i].toString(16);
}
callback(url, header);
};
fileReader.readAsArrayBuffer(blob);
}
function getRemoteFileHeader(url, callback) {
var xhr = new XMLHttpRequest();
// Bypass CORS for this demo - naughty, Drakes
xhr.open('GET', '//cors-anywhere.herokuapp.com/' + url);
xhr.responseType = "blob";
xhr.onload = function() {
callback(url, xhr.response);
};
xhr.onerror = function() {
alert('A network error occurred!');
};
xhr.send();
}
function headerCallback(url, headerString) {
printHeaderInfo(url, headerString);
}
function remoteCallback(url, blob) {
printImage(blob);
getBLOBFileHeader(url, blob, headerCallback);
}
function printImage(blob) {
// Add this image to the document body for proof of GET success
var fr = new FileReader();
fr.onloadend = function() {
$("hr").after($("<img>").attr("src", fr.result))
.after($("<div>").text("Blob MIME type: " + blob.type));
};
fr.readAsDataURL(blob);
}
// Add more from http://en.wikipedia.org/wiki/List_of_file_signatures
function mimeType(headerString) {
switch (headerString) {
case "89504e47":
type = "image/png";
break;
case "47494638":
type = "image/gif";
break;
case "ffd8ffe0":
case "ffd8ffe1":
case "ffd8ffe2":
type = "image/jpeg";
break;
default:
type = "unknown";
break;
}
return type;
}
function printHeaderInfo(url, headerString) {
$("hr").after($("<div>").text("Real MIME type: " + mimeType(headerString)))
.after($("<div>").text("File header: 0x" + headerString))
.after($("<div>").text(url));
}
/* Demo driver code */
var imageURLsArray = ["http://media2.giphy.com/media/8KrhxtEsrdhD2/giphy.gif", "http://upload.wikimedia.org/wikipedia/commons/e/e9/Felis_silvestris_silvestris_small_gradual_decrease_of_quality.png", "http://static.giantbomb.com/uploads/scale_small/0/316/520157-apple_logo_dec07.jpg"];
// Check for FileReader support
if (window.FileReader && window.Blob) {
// Load all the remote images from the urls array
for (var i = 0; i < imageURLsArray.length; i++) {
getRemoteFileHeader(imageURLsArray[i], remoteCallback);
}
/* Handle local files */
$("input").on('change', function(event) {
var file = event.target.files[0];
if (file.size >= 2 * 1024 * 1024) {
alert("File size must be at most 2MB");
return;
}
remoteCallback(escape(file.name), file);
});
} else {
// File and Blob are not supported
$("hr").after( $("<div>").text("It seems your browser doesn't support FileReader") );
} /* Drakes, 2015 */
img {
max-height: 200px
}
div {
height: 26px;
font: Arial;
font-size: 12pt
}
form {
height: 40px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<form>
<input type="file" />
<div>Choose an image to see its file signature.</div>
</form>
<hr/>
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 "?