有赞技术 有赞coder

一、写在前面
文件上传是前端很常见的一类场景。图片、视频和文档等等都属于文件范畴,每个文件则是通过 File.Type 进行更细的划分。本文将针对文件上传的一些通用维度场景做简单的剖析和尝试,抛砖引玉,希望共同学习,共同成长。本文案例里使用的组件来源于组件库 zent@7.4.4
二、常见的上传场景及实现
上传的形式或场景各式各样,除了业务级别的封装外,常遇到的通用场景有如下:重复上传
上传预览
拖拽上传
上传裁剪
上传进度可视化
文件压缩
上传前置校验
切片上传
上传加密
暂停&断网续传 ...
2.1 上传前置校验
在文件上传前,经常会需要对文件格式进行校验,我们需要在文件上传/展示预览图前提示用户图片是否完成校验。常用的格式校验:文件类型、文件大小、上传的尺寸我们先看看和文件相关的两个对象的定义:
Blob
和 File
通过定义我们知道,/** A file-like object of immutable, raw data.Blobs represent data that isn't necessarily in a JavaScript-native format. The File interface is based on Blob, inheriting blob functionality and expanding it to support files on the user's system. */
interface Blob {
readonly size: number;
readonly type: string;
arrayBuffer(): Promise<ArrayBuffer>;
slice(start?: number, end?: number, contentType?: string): Blob;
stream(): ReadableStream;
text(): Promise<string>;
}
/** Provides information about files and allows JavaScript in a web page to access their content. */
interface File extends Blob {
readonly lastModified: number;
readonly name: string;
}
Blob
是一个不可变、存储文件原数据的一个类文件,但其并非是JS的原生数据,而 File
继承于 Blob
,使得 Blob
信息扩展为用户操作系统可支持的文件,并使得页面里可以使用 Javascript
访问其文件信息。除了继承与原有的 size 和 type 属性,
File
对象还额外返回 lastModified(返回文件最后修改日期)和 name (文件名)属性。以下是某个文件的 File
实例信息{ lastModified: 1581424451211 lastModifiedDate: Tue Feb 11 2020 20:34:11 GMT+0800 (中国标准时间) name: "计算机网络.pdf" size: 70809807 type: "application/pdf" webkitRelativePath: ""}通过上面信息,我们可以很轻松地校验文件类型和文件大小。具体的实现我们接着看下去。
2.1.1 限制文件上传类型
1.使用 input 自带属性accept
Mime 类型列表属性 | 描述 | 值 | 例子 |
accept | 期望文件类型 | image/* , audio/* , video/* ... | image/jpeg ... |
图1 Input限制上传类型
2.使用文件后缀或 MIME-TYPE// ...const acceptTypes = ['image/png', 'image/jpeg'];const picSlipt = name.split('.');// 切割文件名后缀const picSuffix = `image/${picSlipt[picSlipt.length - 1]}`;// 直接使用解析的文件信息const fileType = file.type;if (acceptTypes.includes(picSuffix) || acceptTypes.includes(fileType)) { console.log('通过文件类型校验!');};//...3.使用二进制文件信息流读取
但我们知道直接更改文件后缀并不会改变文件类型的本质。比如以下我直接更改一张 png 图片后缀为 jpg,那么它就很有可能绕过了我们的规则
image/jpeg
(虽然想要绕过前端的规则校验有非常多的方法)
图2 通过更改png图片后缀绕过前端上传规则
但实际上它还是png图片,我们可以通过图像信息查询网站可以得出该图片信息实际如下:
图3 后缀和类型不一致
上传校验的绕过会给服务器带来很多潜在危险,因此我们可能需要通过更严格的类型校验:文件头信息进行格式鉴别