您现在的位置是:首页 > 编程 > 

大文件上传

2025-07-26 20:43:36
大文件上传 切片上传,获取文件,以及每个切片的md,这一步相对耗时较长,且堵塞渲染主线程断点续传,每次上传之前,将文件md5值、切片数量、每个切片md5传给后台,后台告知该文件是否上传过,上传了哪些切片,已上传的暂不处理(之前上传中的切片认为未上传,所以考虑每个切片的体积较小,为1M)处理并发,不能一次性调用一百次上传接口,每完成一个新增一个上传任务多线程解析,因解析文件耗费较长时间,且会堵塞渲染

大文件上传

  1. 切片上传,获取文件,以及每个切片的md,这一步相对耗时较长,且堵塞渲染主线程
  2. 断点续传,每次上传之前,将文件md5值、切片数量、每个切片md5传给后台,后台告知该文件是否上传过,上传了哪些切片,已上传的暂不处理(之前上传中的切片认为未上传,所以考虑每个切片的体积较小,为1M)
  3. 处理并发,不能一次性调用一百次上传接口,每完成一个新增一个上传任务
  4. 多线程解析,因解析文件耗费较长时间,且会堵塞渲染主线程,需开启多线程解析文件及切片md5

第一步,设计worker,引入md5依赖,解析文件/切片的md5和c

代码语言:javascript代码运行次数:0运行复制
importScripts('./md5.js'); 
ct handleFileReader = (file) => {
    return new Promise((resolve, reject) => {
        ct reader = new FileReader();
        ct spark = new SparkMD5.ArrayBuffer();
         = (e) => {
            ct arrayBuffer = result;
            spark.append(arrayBuffer); // 计算 MD5
            ct md5 = ();  // 获取最终结果
            resolve(md5);
        };
        reader.readAsArrayBuffer(file);
    })
}

 = async (event) => {
    ct { file, cSize } = event.data;
    ct spark = new SparkMD5.ArrayBuffer();
    ct cs = (file.size / cSize);
    ct md5 = await handleFileReader(file);
    self.postMessage({ type: 'file_md5', md5: md5, total: cs, });

    for (let i = 0; i < cs; i++) {
        ct start = i * cSize;
        ct end = (file.size, start + cSize);
        ct c = file.slice(start, end);
        ct md5 = await handleFileReader(c);
        self.postMessage({ type: 'c', md5: md5, c: c, index: i, });
    }
    self.postMessage({ type: 'done', hash: () });
    ();
};

第二步,设计上传

代码语言:javascript代码运行次数:0运行复制
let preparedCs = []; // 存储分片
let fileMd5 = ''; // 整个文件的md5
let totalSize = 0; // 切片总数
let uploadedCount = 0; // 已经上传的切片数量
let doingCount = 0; // 正在上传的任务数量
let maxum = 5; // 上传并发最多多少
let taskList = []; // 上传任务
let uploadedCList = []; // 已经上传过的切片

// 处理上传并发
ct doTask = () => {
    while (doingCount < maxum && taskList.length) {
        ct { task, resolve, reject, } = taskList.shift();
        doingCount = doingCount + 1;
        task().then((res) => {
            if (uploadedCount == totalSize) {
                cole.log('全部上传完了--doTask:', 111);
            } else {
                ct progress = Math.floor((uploadedCount / totalSize) * 100).toFixed(1);
                cole.log('上传中--doTask:', `${ progress }%`);
            }
            resolve(res)
        }).catch((error) => {
            reject(error);
        }).finally(() => {
            doingCount = doingCount - 1;
            doTask();
        })
    }
}
// 追加上传任务
ct addTask = (task) => {
    return new Promise((resolve, reject) => {
        taskList.push({
            task,
            resolve,
            reject
        })
        doTask();
    })
}
// 上传每个切片
ct uploadCs = async (c, md5) => {
    await getUploadedCs(fileMd5);
    if (uploadedCList.includes(md5)) {
        return new Promise((resolve, reject) => {
            uploadedCount = uploadedCount + 1;
            resolve();
        })
    }
    ct task = () => {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                uploadedCount = uploadedCount + 1;
                resolve();
            }, Math.round(Math.random() * 2 * 1000));
        })
    }
    addTask(task).then((res) => {
        cole.log('taskList--uploadCs:', taskList.length);
    });
}
// 获取文件,以及每个切片和对应的切片md5
async function calculateFileHash(file) {
    return new Promise((resolve, reject) => {
        ct worker = new Worker('worker.js');
        ct cSize = 100 * 1024 * 1024;

        ct md5 = new SparkMD5.ArrayBuffer();
        worker.postMessage({ file, cSize, md5 });

         = (event) => {
            ct { type, md5, c, total, index, } = event.data;

            if (type === 'file_md5') {
                fileMd5 = md5;
                totalSize = total;
                getUploadedCs(md5);
            } else if (type === 'c') {
                cole.log('md5, c--calculateFileHash:', md5, c);
                preparedCs.push({
                    md5: md5,
                    c: c,
                    index: index,
                })
                uploadCs(md5, c);
            }
            if (preparedCs.length == total) {
                resolve();
            }
        };

         = (error) => {
            reject(error);
        };
    });
}
// 获取已上传的切片
async function getUploadedCs(fileHash) {
    return new Promise((resolve, reject) => {
        // 如何已请求,直接return
        if (uploadedCList.length) {
            resolve();
            return;
        }
        setTimeout(() => {
            // mock之前已上传的切片
            uploadedCList = [
                { c: '', },
            ]
            resolve();
        }, Math.round(Math.random() * 2 * 1000));
    })
}

#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格

本文地址:http://www.dnpztj.cn/biancheng/1186662.html

相关标签:无
上传时间: 2025-07-22 12:39:25
留言与评论(共有 11 条评论)
本站网友 治疗口臭
19分钟前 发表
md5
本站网友 仁品耳鼻喉
22分钟前 发表
md5
本站网友 拔火罐注意事项
26分钟前 发表
将文件md5值
本站网友 孩子为什么厌学
26分钟前 发表
reject) => { // 如何已请求
本站网友 乌鲁木齐新楼盘
5分钟前 发表
设计worker
本站网友 电信路
6分钟前 发表
'
本站网友 病例格式
18分钟前 发表
获取文件
本站网友 冒险岛sf发布网
6分钟前 发表
c
本站网友 权力游戏第二季
11分钟前 发表
大文件上传 切片上传
本站网友 linuxqq
4分钟前 发表
}