npm包file-type之文件类型

最近做一个需求,只是单纯的图片上传,结果测试出现图片上传成功,但是放到产品里面黑了,而且只是两张图片会这样,本来打算是暂不解决,因为找不出问题。后来产品说最好能研究一下为什么。

后来是测试说不行的那两张图片是直接修改过后缀的,于是就不予解决了。自己上网查了查,原来每个文件的文件字节流开头内容都会有一个文件类型的标记,其实文件字节流就是这个文件,改了后缀名,这个文件字节流的文件类型标记是不会被修改的。

一般来说,前端上传都是input的accept那边限制一下,然后通过文件名的后缀再拦截一下,我是从来没有通过字节流去判断文件类型。有找到一个file-type的npm包,专门做这个的,下载试了一下,也可以去npm官网看看:

安装:npm install file-type

复制的几个说明:

Detect the file type of a Buffer/Uint8Array/ArrayBuffer

The file type is detected by checking the magic number of the buffer.

This package is for detecting binary-based file formats, not text-based formats like .txt, .csv, .svg, etc.

里面也介绍了可以检测的文件,可以自己去看看:

https://www.npmjs.com/package/file-type

这边用vue试了试这个包,代码:

<input type="file" id="inputFile" @change="handleChange" />


import FileType from 'file-type/browser';
export default defineComponent({
  setup(){
    const handleChange = (e) => {
      const file = e.target.files[0];
      FileType.fromBlob(file).then((res) => {
        console.log(res)
      }, (err) => {
        console.log(err)
      })
    }
    return {
      handleChange
    }
  }
})

尝试了修改后缀,得到的还是修改之前的文件类型,这个包找了一下,没有提供js引入的版本,看了看代码,core.js里面的_fromTokenizer把各个文件类型要检测的都提供了,参考里面的代码写了个图片png和jpg检测的demo:

<input type="file" onchange="handleChange(event)" />


function handleChange(event) {
  const file = event.target.files[0];
  const reader = new FileReader();
  reader.onload = () => {
    let fileType = typeResult(reader.result);
    console.log(fileType);
  };
  reader.readAsArrayBuffer(file);
}
function _check(buffer, headers) {
  options = {
    offset: 0
  };
  for (const [index, header] of headers.entries()) {
    if (header !== buffer[index + options.offset]) {
      return false;
    }
  }
  return true;
}
function typeResult(arryBUffer) {
  const buffer = new Uint8Array(arryBUffer);
  const check = (header, options) => _check(buffer, header);
  if (check([0xFF, 0xD8, 0xFF])) {
    return {
      ext: 'jpg',
      mime: 'image/jpeg'
    };
  }
  if (check([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A])) {
    return {
      ext: 'png',
      mime: 'image/png'
    };
  }
  return undefined
}

测试是可以检测,因为没有深入了解字节流的含义,里面检测其他类型有很多不同的判断,png其实还有其他判断,这边给省略了:

case 'IDAT':
  return {
    ext: 'png',
    mime: 'image/png'
  };
case 'acTL':
  return {
    ext: 'apng',
    mime: 'image/apng'
  };

里面代码还有截取字节流,还有判断两张参数的,还有判断第几个开始的,看起来很复杂。

相对来说,用input的accept进行拦截应该是满足需求了,知道了这个,如果以后后台出现类型不符合或者需求需要,就不会没有一点概念了。

来源:coding个人笔记,本文观点不代表自营销立场,网址:https://www.zyxiao.com/p/135241

发表评论

登录后才能评论
服务中心
服务中心
联系客服
联系客服
侵权联系 投诉举报
返回顶部
河南,挺住!郑州,挺住!一起为他们加油!!