I'm new to working with asynchronous tasks and I'm going crazy. When I finish what I have in hand I will be able to study more about this, but now I'm running out 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 it is an image . There are many methods out there that parse the extension or return the mime/type but it is wrong as you can try changing the extension to an mp3 and jpg and it will tell you that the mime is jpg.
I started 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 is that the code that I started to make I don't 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, read its initial 4 bytes, compare it and if it really is among those admitted, then show a preview... if not, then an error message is displayed saying invalid file.
What I need is for the checkFileType function to return a value to me $('input[type=file]#imagencabecera').change(function()
and so, after validation, if it is correct, the preview is shown on the screen.
This is the code that remains to be tweaked:
$('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.
The simplest is to use promises . To do this, you must first define a promise which will execute the function
checkFileType
. Then, consume the promise so that when the execution of is finished,checkFileType
what you want is executed. This is how the JS asynchrony is fixed.You can insert this code in
$('input[type=file]#imagencabecera').change()
.You have two options:
Promises (ES6)
Promises were introduced in ES2015 (aka ES6) and are a solution proposed by ECMAScript to the famous callback hell. Promises receive a function with two parameters as a callback:
The function
resolve
is used to indicate that a piece of data is going to be delivered by the one who expects the promise. The functionreject
is used to indicate that something in the process has failed.Callbacks (ES5)
This form is the one used de facto in ES5. It consists of passing a function as a parameter to be executed once the main function has finished its process.