使用webWorker计算文件分片hash

引入: hash的计算属于CPU密集型,会阻塞主线程。如果大文件主线程更是会阻塞很久,所以采用webWorker计算hash,把计算结果输出即可。

主线程:

const input = document.querySelector('input');
const chunkSize = 1024 ** 2 * 10 // 设置每个chunk为2M
input.addEventListener('change', async function () {
    const file = this.files[0];

    // 计算chunks 数量
    const chunks = Math.ceil(file.size / chunkSize)
    // worker最大创建数量
    const maxWorkers = navigator.hardwareConcurrency || 4
    // 每个worker需分配chunk量
    const workerChunks = Math.ceil(chunks / maxWorkers)

    let result = []
    let count = 0
    for(let i = 0; i < maxWorkers; i++) {
        //创建worker
        const worker = new Worker('./worker.js', {
            type: 'module'
        });

        //当前worker需要处理chunks的起始index
        const start = i * workerChunks
        //当前worker需要处理chunks结束的index
        const end = Math.min((i + 1) * workerChunks, chunks)

        //将尽可能的工作都交给worker工作
        worker.postMessage({index: i, file, start, end, chunkSize})
        worker.addEventListener('message', (e) => {
            //合并worker工作结果
            result = [...result, ...(e.data)]
            count++
            if(count >= maxWorkers) {
                //全部worker工作结束后,对结果排序
                result = result.sort((a, b) => a.index - b.index)
                // 获取结果
                console.log(result)
            }
        })
    }
}

worker.js

//使用SparkMD5计算文件hash  https://cdnjs.cloudflare.com/ajax/libs/spark-md5/3.0.2/spark-md5.min.js
import './md5.min.js' 

self.addEventListener('message', async (e) => {
    const { file, start, end, chunkSize, index } = e.data
    console.log(`worker${index}开始工作`)
    const result = []
    for (let i = start; i < end; i++) {
        //获取当前chunk的blob起始的位置
        const blobStart = i * chunkSize;
        //获取当前chunk的blob结束的位置
        const blobEnd = Math.min(file.size, (i + 1) * chunkSize)
        //从原始文件中截取出 chunk
        const chunkFile = file.slice(blobStart, blobEnd)
        //计算hash
        const chunkHash = await getFileChunkHash(chunkFile)
        result.push({
            index: i,
            start: blobStart,
            end: blobEnd,
            chunkFile,
            chunkHash
        })
    }
    self.postMessage(result)
})

//计算hash函数
function getFileChunkHash (file) {
    return new Promise((reslove, reject) => {
        const spark = new SparkMD5.ArrayBuffer()
        const fileReader = new FileReader()
        fileReader.onload = (e) => {
            const arrayBuffer = e.target.result
            spark.append(arrayBuffer)
            reslove(spark.end())
        }
        fileReader.readAsArrayBuffer(file)
    })
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值