loading

严格判断文件上传类型

注意:前端判断只能是尽量覆盖所有类型,实际上最可靠的还是靠后端判断

前端胖头鱼:遇到一个小米手机文件上传读取不到后缀,当时也尝试用文中的方法,但是难以覆盖全,还是会判断不对。最后还是依赖后端解决的

# 常规类型校验

通常是通过input元素的accept属性来限制文件的类型:

<input id="file" type="file" accept="image/*" />
1

缺点:可通过浏览器控制台删除 accept 属性,绕过限制

或者通过截取文件名后缀的方式来判断:

const ext = file.name.substring(file.name.lastIndexOf('.') + 1);
1

缺点:可通过本地修改文件扩展名,绕过限制

但是其实同一种类型的文件,他们的十六进制头信息是完全相同的。可以根据头信息来判断文件类型了。

# 1. 将文件转为十六进制字符串

在获取文件对象后,可以通过FileReader API来读取文件的内容,然后将结果转为Unicode编码,再转为十六进制,以下是封装的将文件转为十六进制字符串的方法:

async blobToString(blob) {
  return new Promise(resolve => {
    const reader = new FileReader()
    reader.onload = function() {
      const res = reader.result
        .split("") // 将读取结果分割为数组
        .map(v => v.charCodeAt()) // 转为 Unicode 编码
        .map(v => v.toString(16).toUpperCase()) // 转为十六进制,再转大写
        .map(v => v.padStart(2, "0")) // 个位数补0
        .join(" "); // 转为字符串
      resolve(res)
    }
    reader.readAsBinaryString(blob) // 将文件读取为二进制字符串
  })
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 2. 判断文件类型

没有必要将整个文件转为十六进制,我们只需要截取文件的前几个字节,然后将截取后的文件转为十六进制,再进行比对就可以了:

// 判断是否为 jpg 格式
async function isJpg(file) {
  const res = await blobToString(file.slice(0, 3))
  return res === 'FF D8 FF'
}
// 判断是否为 png 格式
async function isPng(file) {
  const res = await blobToString(file.slice(0, 4))
  return res === '89 50 4E 47'
}
// 判断是否为 gif 格式
async function isGif(file) {
  const res = await blobToString(file.slice(0, 4))
  return res === '47 49 46 38'
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 常用文件的文件头(十六进制)

JPEG (jpg), 文件头:FFD8FF

PNG (png), 文件头:89504E47

GIF (gif), 文件头:47494638

TIFF (tif), 文件头:49492A00

Windows Bitmap ( bmp),文件头:424D

CAD (dwg), 文件头:41433130

Adobe Photoshop (psd), 文件头:38425053

Rich Text Format (rtf), 文件头:7B5C727466

XML (xml), 文件头:3C3F786D6C

HTML (html), 文件头:68746D6C3E

Email [thorough only] (eml), 文件头:44656C69766572792D646174653A

Outlook Express (dbx), 文件头:CFAD12FEC5FD746F

Outlook (pst), 文件头:2142444E

MS Word/Excel (xls.or.doc), 文件头:D0CF11E0

MS Access (mdb), 文件头:5374616E64617264204A

WordPerfect (wpd), 文件头:FF575043

Adobe Acrobat (pdf), 文件头:255044462D312E

Quicken (qdf), 文件头:AC9EBD8F

Windows Password (pwl), 文件头:E3828596

ZIP Archive (zip), 文件头:504B0304

RAR Archive (rar), 文件头:52617221

Wave (wav), 文件头:57415645

AVI (avi), 文件头:41564920

Real Audio (ram), 文件头:2E7261FD

Real Media (rm), 文件头:2E524D46

MPEG (mpg), 文件头:000001BA

MPEG (mpg), 文件头:000001B3

Quicktime (mov), 文件头:6D6F6F76

Windows Media (asf), 文件头:3026B2758E66CF11

MIDI (mid), 文件头:4D546864

最近更新时间: 2022/09/28 16:26:36
最近更新
01
2023/07/03 00:00:00
02
2023/04/22 00:00:00
03
2023/02/16 00:00:00