文件上传与下载
1. 前置知识
1.1 Blob 对象
Blob 对象表示一个二进制文件的数据内容,比如图片文件的内容就可以通过 Blob 对象读写。
// 创建 lob 对象
const blob = new Blob(array [, type]);
// 举例
const blob_1 = new Blob(['<a id="a"><b id="b">hey!</b></a>'], {type : 'text/html'});
const blob_2 = new Blob([ JSON.stringify({ hello: 'world' }) ], {type : 'application/json'});第一个参数是数组,成员是字符串或二进制对象,表示新生成的Blob实例对象的内容;第二个参数是配置对象,目前只有一个属性type,表示数据的 MIME 类型。
获取 Blob 对象后,直接打印是获取不到的,我们需要通过FileReader对象,读取 Blob 对象的内容,即文件内容。
const reader = new FileReader();
reader.readAsText(myBlob); // 返回文本,需要指定文本编码,默认为 UTF-8。
reader.onload = function () {
const text = reader.result; // 通过指定 FileReader 实例对象的onload监听函数,在实例的result属性上才拿到文件内容
}浏览器允许使用URL.createObjectURL()方法,针对 Blob 对象生成一个临时 URL,以便于某些 API 使用。
1.2 File 对象
File 对象代表一个文件,用来读写文件信息。它继承了 Blob 对象,或者说是一种特殊的 Blob 对象,所有可以使用 Blob 对象的场合都可以使用它。最常见的使用场合是表单的文件上传控件(<input type="file">),用户选中文件以后,浏览器就会生成一个数组,里面是每一个用户选中的文件,它们都是 File 实例对象。
第一个参数是数组,成员可以是二进制对象或字符串,表示文件的内容;第二个参数表示文件名或文件路径;第三个参数是可选对象,设置实例的属性。
1.3 FileReader 对象
FileReader 对象用于读取 File 对象或 Blob 对象所包含的文件内容。
FileReader.readAsText():返回文本,需要指定文本编码,默认为 UTF-8。FileReader.readAsArrayBuffer():返回 ArrayBuffer 对象。FileReader.readAsDataURL():返回 Data URL。FileReader.readAsBinaryString():返回原始的二进制字符串。
2. 文件上传
2.1 Form 表单提交
直接通过 form 表单提交,也不需要 JS,action 即为接口地址,注意两点,一是类型需要设置为multipart/form-data,二是 input必须设置 name 属性,否则数据无法发送。
2.2 文件接口上传
通过 document.getElementById('file').files[0] 获取 file 对象,再以 formData 形式发送请求。
file 打印出来如下所示:

formData 打印出来如下所示:

打印出来是一个空的Object,但并不是说它的内容是空的,只是它对前端开发人员是透明的,无法查看、修改、删除里面的内容。
FormData 无法得到文件的内容,需要使用 FileReader 读取整个文件的内容:
2.3 大文件分片上传
分片上传思路:
将文件按一定大小(比如 1M)截取成一小份,并将切片带上 hash 值,用于作为标识,简单方式是文件名字+下标来标识,但是文件名修改就失去意义了,因此建议根据文件内容生成
hash,采用spark-md5库。将每个切片文件,当前端获取到本地图片后,利用
Blob.prototype.slice方法(和数组的slice方法相似),将大文件按照一定大小(例如 1M)进行切割,再并发将各个分片上传到服务端,服务端保存每个切片文件的信息。切片上传完成后,服务端根据文件标识进行合并,合并完后删除切片文件。
断点续传思路:
每个分片上传的时候,服务端记录上传好的文件 hash 值,上传成功后返回 hash 值给前端,前端记录 hash 值
重新上传时,将每个文件的 hash 值与记录的 hash 值做比对,如果相同的话则跳过,继续下一个分段的上传。
全部分片上传完成后,服务端根据文件标识进行合并,合并完后删除小文件。
3. 文件下载
3.1 window.open
浏览器可直接浏览的文件类型是不提供下载的,如 txt、png、jpg、gif 等,会直接打开而非下载;
3.2 调用 form 表单的 submit
无法直接下载浏览器可直接预览的文件类型,无法知道下载的进度;
3.3 调用 a 标签的 click
3.4 Blob 对象下载
除了利用已知文件地址路径进行下载,还能够发送请求 api 获取文件流进行下载,利用 Blob 对象可以将文件流转化成 Blob 二进制对象。
基本思路:发请求获取二进制数据,转化为 Blob 对象,利用 URL.createObjectUrl 生成 url 地址,赋值在a标签的href属性上,结合 download 进行下载,即文件流 -> fileReader转Blob对象 -> a标签下载。
3.5 Base64 下载
base64 可以实现任意类型文件的下载,即文件流 -> fileReader转base64 -> a标签下载。
3.4 依赖其他库
通过第三方依赖包来实现,例如 file-saver 等。
4. 总结
4.1 文件上传
formData 上传
Base64 通过字符串上传
4.2 文件下载
调用 window.open(URL)
表单 form.action = URL 调用 submit()
a 标签 href = URL 调用 click()
最后更新于
这有帮助吗?