在访问文件签名之前验证它们



如何在构造函数中访问文件签名之前验证它们?当我运行以下代码时,即使有来自checkBlobSignature()的异常,也会执行构造函数中try/catch之后的代码。我想我应该使用async/await或回调函数,但任何提示,使它更容易为我?

class ImageEditor {
constructor(blobs) {
try {
for (const blob of blobs) {
checkBlobSignature(blob);
}
} catch(e) {
throw e.message;
}

/* 
* Rest of my constructor code that I want to be executed
* if the for loop is finished, i.e. there are no exceptions.
*/
}

checkBlobSignature(blob) {
let fileReader = new FileReader();
fileReader.addEventListener("loadend", this.check.bind(this));
fileReader.readAsArrayBuffer(blob.slice(0, 8));
}

check(e) {
let uint8Array = new Uint8Array(e.target.result);
let signature = "";
for(const uint8 of uint8Array) {
signature += uint8.toString(16);
}
signature = signature.toUpperCase();

switch (true) {
case /^89504E470D0A1A0A/.test(signature): // PNG Hex signature
break;
case /^474946383761/.test(signature): // GIF Hex signature
case /^474946383961/.test(signature): // GIF Hex signature
break;
case /^FFD8FF/.test(signature): // JPEG Hex signature
break;
case /^6674797069736F6D/.test(signature): // MP4 HEX signature
break;
default:
throw "Invalid signature.";
}
}
}

构造函数不能是异步的,但可以定义一个异步静态方法来构造类的实例。

其次,您可以使用Blob.prototype.arrayBuffer()而不是FileReaderArrayBuffer承诺中获得Uint8Array。对于FileReader也可以这样做,但需要显式的承诺构造反模式,所以我不建议这样做。

最后,由于checkBlobSignature不使用this,您也可以将其作为静态方法。

class ImageEditor {
static async from(blobs) {
await Promise.all(Array.from(blobs, ImageEditor.checkBlobSignature));
return new ImageEditor(blobs);
}
static async checkBlobSignature(blob) {
const signatures = [
[0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A], // PNG
[0x47, 0x49, 0x46, 0x38, 0x37, 0x61], // GIF
[0x47, 0x49, 0x46, 0x38, 0x39, 0x61], // GIF
[0xFF, 0xD8, 0xFF], // JPEG
[0x66, 0x74, 0x79, 0x70, 0x69, 0x73, 0x6F, 0x6D], // MP4
];
const maxSignatureLength = Math.max(
...signatures.map(signature => signature.length),
);
const arrayBuffer = await blob.slice(0, maxSignatureLength).arrayBuffer();
const uint8Array = new Uint8Array(arrayBuffer);
if (!signatures.some(
signature => signature.every((byte, index) => byte === uint8Array[index]),
)) {
throw new Error('Invalid signature');
}
}
ImageEditor(blobs) {
/* Rest of my constructor code that I want to be executed
* if the for loop is finished, i.e. there are no exceptions.
*/
}
}

最新更新