I need to verify the file type after upload in my application and in addition to only checking the extension, I have also included magic bytes check. For that, I have used this article:
Following is my method code:
checkFileTypeViaMagicByte(file):boolean {
const filereader = new FileReader();
const blob = file.slice(0, 4);
filereader.readAsArrayBuffer(blob);
filereader.onloadend= (evt) => {
if (evt.target.readyState === FileReader.DONE) {
// @ts-ignore
const uint = new Uint8Array(evt.target.result);
let bytes = []
uint.forEach((byte) => {
bytes.push(byte.toString(16))
})
const hex = bytes.join('').toUpperCase();
console.log("SIGNATURE: " hex);
switch (hex) {
case '89504E47': //image/png
return true;
case '25504446'://application/pdf
console.log("PDF case");
return true;
case 'FFD8FFDB'://image/jpeg
case 'FFD8FFE0':
return true;
default:
return false;
}
};
};
return false;
}
The issue I am having is that FileReader is async and my method always returns false. I need to perform this verification in a method because I have various methods performing checks such as filename allowed, file size etc. How can I solve this issue?
CodePudding user response:
You just need to promisify the filereader.onloadend
function.
checkFileTypeViaMagicByte(file):boolean {
const filereader = new FileReader();
const blob = file.slice(0, 4);
filereader.readAsArrayBuffer(blob);
return new Promise((resolve, reject) => {
filereader.onloadend = (evt) => {
try {
if (evt.target.readyState === FileReader.DONE) {
// @ts-ignore
const uint = new Uint8Array(evt.target.result);
let bytes = [];
uint.forEach((byte) => {
bytes.push(byte.toString(16));
});
const hex = bytes.join("").toUpperCase();
switch (hex) {
case "89504E47": //image/png
resolve(true);
break;
case "25504446": //application/pdf
resolve(true);
break;
case "FFD8FFDB": //image/jpeg
case "FFD8FFE0":
resolve(true);
break;
default:
resolve(false);
}
}
} catch (err) {
reject(err);
}
};
});
}
This function will return a boolean pormise
you need to resolve with then
checkFileTypeViaMagicByte(file).then(res => console.log(res))
or with await/async
syntax.
(async () => {
const result = checkFileTypeViaMagicByte(file)
console.log(result)
})()