前言:本文章的第5、6条实例代码没进行运行校验,有错勿见怪
一、文件上传的两种主要方式
1、二进制blob上传(使用formData对象搭载二进制数据传给后端)
2、base64编码上传(使用fileReader对象把数据转换为base64格式的数据传给后端)
二、文件上传的相关对象
1、file:通过input标签获取的文件对象;
2、blob:不可变的二进制内容,包含很多操作方法;
3、FormData:用于和后端传输的对象(相当于一个货车);
4、fileReader:多用于把文件读取为某种形式,比如使用readAsDataURL()转化为base64格式、使用text文本。
注意:file是blob的一个子类,所以blob上面的方法file对象都有,我们不能把file对象中的文件信息直接传给后端,只能借助FormData对象去上传,把文件以二进制的形式传给后端。关系图如下

三、实例
1、file对象和blob对象可以相互转换
javascript
<div class="cont">
<input type="file" class="file" />
</div>
<script>
const el = document.querySelector(".file");
el.addEventListener("change", (e) => {
const file = e.target.files[0];
const _blob = new Blob([file]);
const _file = new File([_blob], "1.png");
console.log(file, _blob, _file);
});
</script>
运行结果如下

2、实现缩略图展示(转成base64格式)
javascript
<div class="cont">
<input type="file" class="file" />
<img src="" class="img" style="width: 100px; height: 100px" />
</div>
<script>
const el = document.querySelector(".file");
el.addEventListener("change", (e) => {
const file = e.target.files[0];
// 将文件转为base64格式
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = (res) => {
const imgEl = document.querySelector(".img");
imgEl.setAttribute("src", res.target.result);
};
});
</script>
选中图片后

这时候我们能看到图片的地址已被转换成base64格式

3、转换成base64格式上传
javascript
<div class="cont">
<input type="file" class="file" />
</div>
<script>
const el = document.querySelector(".file");
el.addEventListener("change", (e) => {
const file = e.target.files[0];
const fr = new FileReader()
// 将文件转为base64格式
fr.readerAsDataURL(file)
fr.onload = (res) => {
const finalRes = res.target.result
// 以下使用finalRes作为参数进行ajax请求...
}
});
</script>
4、blob流上传
javascript
<div class="cont">
<input type="file" class="file" />
</div>
<script>
const el = document.querySelector(".file");
el.addEventListener("change", (e) => {
const file = e.target.files[0];
const fd = new FormData()
fd.append("file", file)
// 以下使用fd作为参数进行ajax请求...
});
</script>
5、多文件上传
以上3、4实例实现的是单文件上传,如果我们要实现多文件上传则要在input标签中加入multiple属性,其实本质就是遍历单文件上传。
javascript
<div class="cont">
<input type="file" class="file" multiple />
</div>
<script>
const el = document.querySelector(".file");
el.addEventListener("change", (e) => {
const files = e.target.files;
if (files && files.length) {
files.forEach(ele => {
const fd = new FormData()
fd.append(ele.name, ele)
// 以下使用fd作为参数进行ajax请求...
})
}
});
6、分片上传
其实很好理解,就是按照file对象返回的size属性进行切割上传。比如选择的文件是100M,我们按照每段2M的大小对文件进行切割,然后遍历上传。如下面代码:
javascript
<div class="cont">
<input type="file" class="file" />
<-- 展示上传进度 -->
<div class="process"></div>
</div>
<script>
const el = document.querySelector(".file");
el.addEventListener("change", async (e) => {
const file = e.target.files[0];
// 当前进度
let process = 0
// 文件总大小
const fileSize = file.size
// 每段文件字节大小
const sectionSize = 2 * 2024 * 2024
// 当前已传文件字节大小
let currentSize = 0
while(currentSize < fileSize) {
const fd = new formData()
fd.append(file.name, file.slice(currentSize, currentSize+sectionSize))
await // 此后使用fd作为参数进行ajax请求...
process = Math.min(Math.cell((currentSize / fileSize) * 100, 100))
currentSize += sectionSize
}
});