前端分片上传文件

//获取数据类型
const GetDataType = any => {
    let str = Object.prototype.toString.call(any);
    return str.slice(8, -1);
}

//uploadFile方法基础配置
const uploadBaseConfig = {
    file: File,
    maxSize: 4 * 1024 * 1024,
    taskLength: 1,
}

//文件上传方法
export async function uploadFile(config = uploadBaseConfig) {
    return new Promise(resolve => {
        let taskResolve = []; //所有请求的相应

        if (GetDataType(config) === "File") {
            config = {
                ...uploadBaseConfig,
                file: arguments[0],
                ...arguments[1],
            };
        }
        const { file, maxSize, taskLength } = config; //uploadFile 请求配置对象
        if (GetDataType(file) !== "File") {
            return Promise.reject(new Error("文件不能为空"));
        };

        //请求方法
        const uploadMethod = formData => axios({
            method: "post",
            url: `/index/util/upload`,
            data: formData,
            headers: {
                "Content-Type": "multipart/form-data"
            },
        });

        // 小于4Mb直接传
        if (file.size <= maxSize) {
            const form = new FormData();
            form.append("file", file);
            uploadMethod(form).then(res => {
                resolve(res);
            });
            return
        }

        //Symbol兼容处理
        const makeIterator = arr => {
            if (/native code/.test(Symbol.toString())) {
                return arr[Symbol.iterator]();
            }
            let nextIndex = 0;
            return {
                next() {
                    if (nextIndex < arr.length) {
                        return { value: arr[nextIndex++], done: false }
                    }
                    return { value: undefined, done: true }
                }
            }
        };

        //请求队列
        const task = arr => {
            const { value } = arr.next();
            if (value) {
                Promise.all(value.map(item => uploadMethod(item))).then(result => {
                    taskResolve = taskResolve.concat(result);
                    setTimeout(() => task(arr), 1000 * 5);
                });
            } else {
                resolve(taskResolve)
            }
        };

        const length = Math.ceil(file.size / maxSize); //文件分片长度 
        const taskArrLength = Math.ceil(length / taskLength);//promise任务队列长度
        //切割文件对象
        const arr = [...new Array(length)].map((item, index) => {
            const start = index * maxSize;
            const end = start + maxSize;
            const fileContent = new File(// 文件内容
                [file.slice(start, end)],
                file.name,
                { type: file.type }
            );
            const form = new FormData();
            form.append("file", fileContent);

            return form;
        });

        // 队列数组
        const taskArr = [... new Array(taskArrLength)].map((item, index) => {
            const start = index * taskLength;
            const end = start + taskLength;
            return arr.slice(start, end);
        });
        const tasklist = makeIterator(taskArr); //生成任务队列
        task(tasklist);
    })

};