前端对大文件进行分割上传

前端利用h5的File api读文件进行分割

  const chunkSize = 2 * 1024 * 1024; // 每个chunk的大小,设置为2兆
        const blobSlice =
            File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
        const hashFile = (file) => {
            return new Promise((resolve, reject) => {
                const chunks = Math.ceil(file.size / chunkSize);
                let currentChunk = 0;
                const spark = new SparkMD5.ArrayBuffer();
                const fileReader = new FileReader();
                function loadNext() {
                    const start = currentChunk * chunkSize;
                    const end = start + chunkSize >= file.size ? file.size : start + chunkSize;
                    fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
                }
                fileReader.onload = e => {
                    spark.append(e.target.result); // Append array buffer
                    currentChunk++;
                    if (currentChunk < chunks) {
                        loadNext();
                        console.log(`第${currentChunk}分片解析完成,开始解析${currentChunk + 1}分片`);
                    } else {
                        console.log('finished loading');
                        const result = spark.end();
                        // 如果单纯的使用result 作为hash值的时候, 如果文件内容相同,而名称不同的时候
                        // 想保留两个文件无法保留。所以把文件名称加上。
                        const sparkMd5 = new SparkMD5();
                        sparkMd5.append(result);
                        sparkMd5.append(file.name);
                        const hexHash = sparkMd5.end();
                        resolve(hexHash);
                    }
                };
                fileReader.onerror = () => {
                    console.warn('文件读取失败!');
                };
                loadNext();
            }).catch(err => {
                console.log(err);
            });
        }
  // 使用Blob.slice方法来对文件进行分割。
            // 同时该方法在不同的浏览器使用方式不同。
            const fileDom = $('#file')[0];
            // 获取到的files为一个File对象数组,如果允许多选的时候,文件为多个
            const files = fileDom.files;
            const file = files[0];
            if (!file) {
                alert('没有获取文件');
                return;
            }
            const blockCount = Math.ceil(file.size / chunkSize); // 分片总数
            const axiosPromiseArray = []; // axiosPromise数组
            const hash = await hashFile(file); //文件 hash 
            // 获取文件hash之后,如果需要做断点续传,可以根据hash值去后台进行校验。
            // 看看是否已经上传过该文件,并且是否已经传送完成以及已经上传的切片。
            for (let i = 0; i < blockCount; i++) {
                const start = i * chunkSize;
                const end = start + chunkSize >= file.size ? file.size : start + chunkSize;
                // 构建表单
                const form = new FormData();
                form.append('file', blobSlice.call(file, start, end));
                form.append('name', file.name);
                form.append('total', blockCount);
                form.append('index', i);
                form.append('size', file.size);
                form.append('hash', hash);
                console.log(blockCount, blobSlice.call(file, start, end), i, start, end, file.size);
                // ajax提交 分片,此时 content-type 为 multipart/form-data
                const axiosOptions = {
                    onUploadProgress: e => {
                        // 处理上传的进度
                        // console.log(blockCount, i, e, file);
                    },
                };
                // 加入到 Promise 数组中
     
                axiosPromiseArray.push(axios.post('/uploadFile', form, axiosOptions));
            }
            // 等待所有的请求完毕 然后发送合并的请求
            await axios.all(axiosPromiseArray).then((result) => {
                // 合并chunks
                const data = {
                    size: file.size,
                    name: file.name,
                    total: blockCount,
                    hash
                };
                const form = new FormData();
                form.append('size', file.size);
                form.append('name', file.name);
                form.append('total', blockCount);
                form.append('hash', hash);
                console.log(result);
                axios.post("/file/chunks", form).then(res => {
                    console.log(res)
                })
            }).catch((err) => {

            });
            console.log("全部上传完毕");
        })
  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值