Question:
I'm new to working with asynchronous tasks and I'm freaking out. When I finish what I have in hand I will be able to study more about this, but now I am short of time.
My question is the following: I need to validate a form from the client (I will also do it from the server, but I want double security). What I want to validate is when uploading a file, verify that this is an image . There are many methods out there that parse the extension or return the mime / type but it is wrong, since you can try it by changing the extension to an mp3 and jpg and it will tell you that the MIME is jpg.
I started by seeing an example that read 4 bits of the file and then depending on those 4 bytes you can know what type of file it is . What happens that the code that I started to do not know how to implement it.
What I want it to do is the following: from the form you select an image, and when you select one, it reads its initial 4 bytes, compares it and if it really is among those admitted, then a preview is shown … if not, then an error message is displayed saying invalid file.
What I need is that the checkFileType function returns a value to $('input[type=file]#imagencabecera').change(function()
and so after validation if it is correct to show the preview on the screen.
This is the missing code to tweak:
$('input[type=file]#imagencabecera').change(function(){
var file = (this.files[0].name).toString();
var type = (this.files[0].type).toString();
var reader = new FileReader();
console.log(type);
$('#file-info').text('');
$('#file-info').text(file);
reader.onload = function (e){
$('#filepreview img').attr('src', e.target.result);
}
reader.readAsDataURL(this.files[0]);
});
function checkFileType(file){
if (window.FileReader && window.Blob)
// All the File APIs are supported. Si soporta HTML5 FileReader y Blob
{
var slice = file.slice(0,4); // Get the first 4 bytes of a file
var reader = new FileReader(); // Create instance of file reader. It is asynchronous!
reader.readAsArrayBuffer(slice); // Read the chunk file and return to blob
reader.onload = function(e) {
var buffer = reader.result; // The result ArrayBuffer
var view = new DataView(buffer); // Get access to the result bytes
var signature = view.getUint32(0, false).toString(16); // Read 4 bytes, big-endian,return hex string
switch(signature) // Every file has a unique signature, we can collect them and create a data lib
{
case "89504e47": file.verified_type = "image/png"; break;
case "47494638": file.verified_type = "image/gif"; break;
case "FFd8FFe0": file.verified_type = "image/jpeg"; break;
case "FFd8FFe1": file.verified_type = "image/jpeg"; break;
case "FFd8FFe2": file.verified_type = "image/jpeg"; break;
case "FFd8FFe3": file.verified_type = "image/jpeg"; break;
case "FFd8FFe8": file.verified_type = "image/jpeg"; break;
default: file.verified_type = 0;
}
}
}
else
// File and Blob are not supported
{
}
}
Thank you so much for everything.
Answer:
The simplest is to use promises . To do this, you must first define a promise which will execute the checkFileType
function. Then, consume the promise so that when the execution of checkFileType
, whatever you want is executed. This is how the JS asynchrony is solved.
var checkFileTypePromise = new Promise(function(resolve, reject) {
// Ejecutamos la función y obtenemos el 'verified_type'
verified_type = checkFileType(file);
// Si queremos resolver (finalizar correctamente) la promesa,
// utilizamos la función 'resolve(resultado)'.
// Si queremos lanzar algún error, utilizamos 'reject(razón)'
resolve(verified_type);
});
checkFileTypePromise
.then(function(result) {
// La promesa ha finalizado correctamente.
// En 'result' tenemos el valor que nos devuelve la función
console.log(result);
});
.catch(function(reason) {
// La promesa ha finalizado con algún error.
console.err(result);
});
This code can be inserted in $('input[type=file]#imagencabecera').change()
.