美文网首页
秒传,分片上传,断点续传

秒传,分片上传,断点续传

作者: Cherry丶小丸子 | 来源:发表于2024-03-19 10:11 被阅读0次

1、什么是秒传

通俗的说,你把要上传的东西上传,服务器会先做 MD5 校验,如果服务器上有一样的东西,它就直接给你个新地址,其实你下载的都是服务器上的同一个文件,想要不秒传,其实只要让 MD5 改变,就是对文件本身做一下修改(改名字不行),例如一个文本文件,你多加几个字,MD5 就变了,就不会秒传了

小文件 MD5 生成
calcFileMd5(file, chunkSize) {
    return new Promise((resolve, reject) => {
        let start = performance.now();
        let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
        let chunks = Math.ceil(file.size / chunkSize);
        let currentChunk = 0;
        let spark = new SparkMD5.ArrayBuffer();
        let fileReader = new FileReader();

        fileReader.onload = function(e) {
            spark.append(e.target.result);
            currentChunk++;
            if (currentChunk < chunks) {
                loadNext();
            } else {
                let end = performance.now();
                resolve(spark.end());
                console.log(end - start)
            }
        };

        fileReader.onerror = function(e) {
            reject(e);
        };

        function loadNext() {
            let start = currentChunk * chunkSize;
            let end = start + chunkSize;
            if (end > file.size){
                end = file.size;
            }
            fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
        }
        loadNext();
    });
},

/**
 * 调用
 * @param {Object} info.file 文件
 * @param {Object} 5M/块
 */
this.calcFileMd5(info.file, 5242880).then(e => {
    // 获取到文件的 md5
    console.log('文件哈希是:', e);
}).catch(e => {
    // 处理异常
    console.error(e);
});
大文件 MD5 生成,优化

https://blog.csdn.net/qq_41614928/article/details/113974902

利用 window.requestIdleCallback() 方法
async uploadFile(file) {
    let start = performance.now();
    const hash = await this.fileHash1111(file)
    let end = performance.now();
    console.log('文件哈希是:', hash)
    console.log('用时:', end - start)
},

async fileHash(file) {
    const chunks = [];
    let cur = 0;
    while (cur < file.size) { // file 为 e.target.files[0]
        const chunkSize = 5 * 1024 * 1024; // 5MB/片
        chunks.push({ index: cur, file: file.slice(cur, cur + chunkSize)});
        cur += chunkSize;
    }
    return new Promise( resolve => {
        const spark = new SparkMD5.ArrayBuffer();
        let count = 0;
        const appendToSpark = async file => {
            return new Promise( resolve => {
                const reader = new FileReader();
                reader.readAsArrayBuffer(file);
                reader.onload = e => {
                    spark.append(e.target.result);
                    resolve();
                }
            })
        }
        const workLoop = async deadline => {
            while (count < chunks.length && deadline.timeRemaining() > 1) {
                // 浏览器存在空闲时间
                await appendToSpark(chunks[count].file);
                count++;
                if (count < chunks.length) {
                    this.hashProgress = Number( ((100 * count) / chunks.length).toFixed(2) );
                } else {
                    this.hashProgress = 100
                    resolve(spark.end());
                }
            }
            window.requestIdleCallback(workLoop); // 给 workLoop 函数一个浏览器状态参数 deadline
        }
        window.requestIdleCallback(workLoop); // 给 workLoop 函数一个浏览器状态参数 deadline
    })
},
利用 Web Worker 方法
├── public
│   ├── hash.js              // 快速计算文件 hash 入口文件 (放在 public 文件夹是为了方便 Worker 访问)
│   └── spark-md5.min.js     //需要用到 spark-md5 库
├── pages           
│   └── file_hash.vue       // 快速计算文件 hash
│   ...


如果不想放入 public 文件夹中,则需要安装 worker-loader
使用方案参考:https://www.cnblogs.com/gerry2019/p/11456035.html
file_hash.vue
async uploadFile(file) {
    let start = performance.now();
    const hash = await this.fileHash1111(file)
    let end = performance.now();
    console.log('文件哈希是:', hash)
    console.log('用时:', end - start)
},

async fileHash(file) {
    const chunks = [];
    let cur = 0;
    while (cur < file.size) { // file 为 e.target.files[0]
        const chunkSize = 5 * 1024 * 1024; // 5MB切片
        chunks.push({ index: cur, file: file.slice(cur, cur + chunkSize)});
        cur += chunkSize;
    }

    return new Promise( resolve => {
        const worker = new Worker('/hash.js') // 开启一个外部进程
        worker.postMessage({ chunks }) // 给外部进程传递信息
        worker.onmessage = e => { // 接收外部 Worker 回传的信息
            const { progress, hash } = e.data;
            let hashProgress = Number(progress.toFixed(2)) // 计算 hash 值的进度条
            console.log(hashProgress)
            if (hash) {
                resolve(hash) // 得到计算出来的 hash
            }
        }
    })
},
hash.js
// 引入 spark-md5
self.importScripts('spark-md5.min.js');

// 接收主线程传递的参数
self.onmessage = e => {
    const { chunks } = e.data;
    const spark = new self.SparkMD5.ArrayBuffer();

    let progress = 0, count = 0;

    const loadNext = index => {
        if (index == 0) {
            progress = 0;
            count = 0;
        }
        const reader = new FileReader();
        reader.readAsArrayBuffer(chunks[index].file);
        reader.onload = e => {
            count++;
            spark.append(e.target.result); // 将读取的内容添加入 spark 生成 hash
            if (count == chunks.length) {
                self.postMessage({
                    progress: 100,
                    hash: spark.end() // 完成计算,返回 hash 值
                })
            } else {
                progress += 100 / chunks.length;
                self.postMessage({ progress });
                loadNext(count);
            }
        }
    }
    loadNext(0);
}

2、什么是分片上传

分片上传,就是将所要上传的文件,按照一定的大小,将整个文件分隔成多个数据块来进行分别上传,上传完之后再由服务端对所有上传的文件进行汇总整合成原始的文件

3、什么是断点续传

断点续传是在下载或上传时,将下载或上传任务(一个文件或一个压缩包)人为的划分为几个部分,每一个部分采用一个线程进行上传或下载,如果碰到网络故障,可以从已经上传或下载的部分开始继续上传或者下载未完成的部分,而没有必要从头开始上传或者下载

https://www.cnblogs.com/viewts/p/10820785.html

相关文章

网友评论

      本文标题:秒传,分片上传,断点续传

      本文链接:https://www.haomeiwen.com/subject/klxfydtx.html