JS如何判断文件的真实类型

1,776 阅读2分钟

背景

当我们用input导入文件后获取到文件对象file,只能从file对象的name和type去判断文件表面上的类型,比如:

image.png

文件的file对象如下:

image.png

但是,如果把文件的后缀名改一下,改成txt类型,

image.png

再读取下file文件看看

image.png

这时候就会误导我们对文件真实类型的判断

思路

文件在内存中的都是以二进制数据的形式保存,计算机判断文件的类型其实是根据二进制数据当中的“魔数”去判断的,大部分文件的二进制数据中前几个字节内容都是固定的,这几个固定的内容组成的一串数字就是“魔数”,我们可以根据这个去判断文件的真实类型,比如常见的图片类型如下:

image.png

方案

这里就拿jpeg这个类型来举例

const checkIsJpeg = (file: File) => {
    const jpegHeader = [0xff, 0xd8, 0xff];// jpeg类型的魔数
    const reader = new FileReader();
    reader.onload = () => {
      // 读取文件二进制流
      const arrayBuffer = reader.result;
      // 用二进制视图定型数组的Uint8Array获取文件的魔数
      const uint8Array = new Uint8Array(arrayBuffer);
      const magicNum = uint8Array.slice(0, jpegHeader.length);
      // 判断该文件魔数是否符合jpeg的魔数
      const isJpeg = jpegHeader.every((header, index) => {
        return header === uint8Array[index];
      });

      console.log('源文件', file);
      console.log('jpeg的魔数', jpegHeader);
      console.log('文件流中的魔数', { magicNum });
      console.log('文件真实类型是否为jpeg', isJpeg);
    };
    reader.readAsArrayBuffer(file);
  };

效果如下

先上传一张jpeg

image.png

看下输出结果

image.png

再将文件后缀改为txt

image.png

看下输出结果

image.png

可见,不管文件后缀怎么修改,文件的二进制数据是不变的,我们可以根据二进制数据去判断文件的真实类型

补充

开发中可以用 file-type 这个库去判断文件的真实类型

参考资料

魔数

定型数组