最近在做大文件上传的需求,所以就有了这一系列前端文件上传功能的记录。
具体功能点
- 实现限制文件同时上传的最大个数
- 超过文件个数的上传,等待某个文件上传成功后再执行
实现
关键点:用队列来记录上传的数据。上传完成、上传败或者上传暂停就出队,开始上传就入队,队列的长度就是正在上传的文件个数,所以可以对上传文件个数做限制,入队前先判断队列长度,超过长度只入队不发送请求(不上传,状态变为:等待中),没超过长度,入队以及发请求。每次一个文件上传完成后(包括上传失败、上传暂停等状态)出队,然后判断队伍的长度,如果超过限制个数,则继续下一个上传请求。
代码
// 定义队列
interface UploadList {
name?: string;
id: string;
size?: number;
status?: string;
progress: {
loaded: number;
total: number;
}[];
uploadId?: string;
cancelReq: any[];
md5?: string;
file?: any;
doneIndex: number;
requestList: any[];
}
let requestQueue = [] as UploadList[];
// 同时上传文件数限制
const fileLimit = 5;
// 入队
requestQueue.push(pagePros.upload.list[index]);
// 出队
requestQueue.shift();
// 上传出队处理
const lineUp = async (data) => {
// 出队
requestQueue.shift();
if (requestQueue.length >= fileLimit) {
handle(data.requestQueue[fileLimit - 1].file, data.requestQueue[fileLimit - 1].id);
}
};
// 处理上传文件
const handleFile = (e, files: FileList | File[]) => {
if (Array.isArray(files)) {
files.forEach((file) => {
const uid = getUid(64);
// 组装下载列表参数
const params: UploadList = {
id: uid,
name: `${pagePros.path}${file.name}`,
size: file.size,
status: 'waiting',
progress: [],
file,
cancelReq: [],
requestList: [],
doneIndex: 0,
};
// 更新下载列表
setPageProps((pre) => {
pre.upload.showText = false;
pre.upload.list = pre.upload.list.concat([params]);
});
// 入队
requestQueue.push(params);
if (requestQueue.length <= fileLimit) {
handle(file, uid);
}
});
}
};