前端文件类型校验

demongao
2937
2023-01-11

通过base64 获取文件头判断文件类型并不准确,如果想要获取文件真实类型,需要获取文件二进制头,每种格式都有特有的二进制头。所以需要前端读取文件流,比较文件头,判断文件真实格式。

function stringToBytes(string) {
  return [...string].map((character) => character.charCodeAt(0))
}

function readBuffer(file, start = 0, end = 2) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.onload = () => {
      resolve(reader.result)
    }
    reader.onerror = reject
    reader.readAsArrayBuffer(file.slice(start, end))
  })
}

function check(headers) {
  return (buffers, options = { offset: 0 }) =>
    headers.every((header, index) => header === buffers[options.offset + index])
}

const isPDF = check(stringToBytes('%PDF'))
const isPNG = check([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])

export const checkFileType = async (file, accept = '*') => {
  const buffers = await readBuffer(file, 0, 8)
  const uint8Array = new Uint8Array(buffers)
  const acceptList = accept.split(',')
  for (let i = 0, length = acceptList.length; i < length; i++) {
    if (acceptList[i] === 'pdf' && isPDF(uint8Array)) return true
    else if (acceptList[i] === 'png' && isPNG(uint8Array)) return true
  }

  return Promise.reject()
}