主题
上传校验
上传校验的核心不是“能不能传”,而是“是否应该让这个文件进入上传流程”。
为什么上传前就要校验
越早拦截,成本越低。
常见原因包括:
- 文件太大
- 文件类型不符合要求
- 图片尺寸或比例不符合要求
- 一次选择的文件数量超限
这些问题如果等到请求发出去才处理,用户体验通常会更差。
最常见的几类校验
上传前最常做的通常是:
- 大小校验
- 类型校验
- 数量校验
- 图片尺寸 / 比例校验
文件大小校验
直接看 file.size:
js
const maxSize = 5 * 1024 * 1024
if (file.size > maxSize) {
throw new Error('文件大小不能超过 5MB')
}这是最基础也最常见的一层。
文件类型校验
先看 file.type
js
const allowedTypes = ['image/jpeg', 'image/png', 'image/gif']
if (!allowedTypes.includes(file.type)) {
throw new Error('文件类型不支持')
}这层成本低,适合先做快速筛选。
也可以看扩展名
js
const ext = file.name.split('.').pop()?.toLowerCase()
const allowedExtensions = ['jpg', 'jpeg', 'png', 'gif']
if (!allowedExtensions.includes(ext)) {
throw new Error('文件扩展名不支持')
}但扩展名只能作为弱校验,因为文件名可以伪造。
更严格时看文件头
如果需要更可靠的类型判断,可以读取文件前几个字节做魔数校验:
js
const signatures = {
'image/jpeg': [0xff, 0xd8, 0xff],
'image/png': [0x89, 0x50, 0x4e, 0x47],
}这比只看文件名更稳,但前端校验本身仍然不是最终安全边界,服务端还要再验一次。
文件数量校验
多文件上传时,不要只校验单个文件,也要校验总数:
js
const files = Array.from(fileInput.files)
if (files.length > 5) {
throw new Error('最多只能上传 5 个文件')
}图片尺寸和比例校验
图片类上传常会进一步校验:
- 宽高
- 长宽比
通常会先把文件转成临时 URL,再用 Image 读取:
js
const url = URL.createObjectURL(file)
const img = new Image()
img.onload = () => {
console.log(img.width, img.height)
URL.revokeObjectURL(url)
}
img.src = url比例校验
js
const ratio = img.width / img.height
const target = 16 / 9
if (Math.abs(ratio - target) > 0.1) {
throw new Error('图片比例不符合要求')
}尺寸校验
js
if (img.width < 800 || img.height < 600) {
throw new Error('图片尺寸过小')
}一个容易误解的点
前端上传校验更多是:
- 提前拦截
- 提升体验
- 减少无效请求
它不是最终安全校验。
真正影响系统安全和数据可信度的规则,服务端必须再执行一次。
使用建议
- 先做低成本校验,例如数量、大小、
file.type。 - 图片类资源再补尺寸和比例校验。
- 规则严格时,可增加魔数校验,但不要把它当最终防线。
- 上传校验始终要有服务端兜底。
