Anda dapat dengan mudah menentukan jenis file MIME dengan JavaScript FileReader
sebelum mengunggahnya ke server. Saya setuju bahwa kita harus memilih pemeriksaan sisi-server daripada sisi-klien, tetapi pemeriksaan sisi-klien masih memungkinkan. Saya akan menunjukkan caranya dan memberikan demo yang berfungsi di bagian bawah.
Pastikan browser Anda mendukung keduanya File
dan Blob
. Semua yang utama harus.
if (window.FileReader && window.Blob) {
// All the File APIs are supported.
} else {
// File and Blob are not supported
}
Langkah 1:
Anda dapat mengambil File
informasi dari <input>
elemen seperti ini ( 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>
Berikut ini adalah versi drag-and-drop di atas ( 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>
Langkah 2:
Kami sekarang dapat memeriksa file dan mencari header dan tipe MIME.
✘ Metode cepat
Anda bisa bertanya kepada Blob tentang jenis file MIME apa pun yang diwakilinya menggunakan pola ini:
var blob = files[i]; // See step 1 above
console.log(blob.type);
Untuk gambar, tipe MIME kembali seperti berikut:
gambar / gambar jpeg
/ png
...
Peringatan: Jenis MIME terdeteksi dari ekstensi file dan bisa dibodohi atau dipalsukan. Satu dapat mengubah nama .jpg
ke .png
dan jenis MIME akan dilaporkan sebagai image/png
.
✓ Metode pemeriksaan header yang benar
Untuk mendapatkan tipe MIME bonafide dari file sisi klien, kita dapat melangkah lebih jauh dan memeriksa beberapa byte pertama dari file yang diberikan untuk membandingkan dengan apa yang disebut angka ajaib . Berhati-hatilah karena itu tidak sepenuhnya langsung karena, misalnya, JPEG memiliki beberapa "angka ajaib". Ini karena formatnya telah berevolusi sejak 1991. Anda mungkin lolos hanya dengan memeriksa dua byte pertama, tetapi saya lebih suka memeriksa setidaknya 4 byte untuk mengurangi false positive.
Contoh tanda tangan file JPEG (4 byte pertama):
FF D8 FF E0 (SOI + ADD0)
FF D8 FF E1 (SOI + ADD1)
FF D8 FF E2 (SOI + ADD2)
Berikut adalah kode penting untuk mengambil file header:
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);
Anda kemudian dapat menentukan tipe MIME yang sebenarnya seperti itu (lebih banyak tanda tangan file di sini dan di sini ):
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;
}
Terima atau tolak unggahan file sesuai keinginan berdasarkan jenis MIME yang diharapkan.
Demo
Ini demo yang berfungsi untuk file lokal dan file jarak jauh (saya harus mem-bypass CORS hanya untuk demo ini). Buka cuplikan, jalankan, dan Anda akan melihat tiga gambar jarak jauh dari berbagai jenis ditampilkan. Di bagian atas Anda dapat memilih file gambar atau data lokal , dan tanda tangan file dan / atau tipe MIME akan ditampilkan.
Perhatikan bahwa meskipun gambar diubah namanya, jenis MIME yang sebenarnya dapat ditentukan. Lihat di bawah.
Tangkapan layar
// 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.
Saya tidak mengerti bagaimana mengapa Anda mengatakan bahwa validasi harus dilakukan di sisi server, tetapi kemudian katakan Anda ingin mengurangi sumber daya server. Aturan emas: Jangan pernah percaya pada input pengguna . Apa gunanya memeriksa tipe MIME di sisi klien jika Anda hanya melakukannya di sisi server. Tentunya itu adalah "pemborosan sumber daya klien yang tidak perlu "?