文件名称重复怎么进行上传限制
前言
前面文章实现了如何优雅的判断文件格式,现在我们来实现如果文件名称重复怎么进行上传?
md5进行hash计算出来的值可以实现不重复上传文件名称,但是如果文件过大的时候hash值计算过慢也是会影响浏览器卡顿,那么怎么进行优化呢?
xdm,接下来我们一起探寻文件上传的奥秘吧!!!
实现
使用web worker进行计算
npm 安装包 spark-md5,spark-md5.min.js单独抽离出来进行使用
创建hash.js进行后台计算
self.importScripts('spark-md5.min.js') self.onmessage = e => { const { chunks } = e.data const spark = new self.SparkMD5.ArrayBuffer() let count = 0 const loadNext = index => { const reader = new FileReader() reader.readAsArrayBuffer(chunks[index].file) reader.onload = e => { count++ spark.append(e.target.result) if (count === chunks.length) { self.postMessage({ hash: spark.end() }) } else { loadNext(count) } } } loadNext(0) }
使用worker执行计算
function calculateHashWorker() { return new Promise(resolve => { worker = new Worker('./static/hash.js') worker.postMessage({ chunks: chunks }) worker.onmessage = e => { console.log(e.data) const { hash } = e.data; if (hash) { resolve(hash) } } }) }
最后得到最终的hash值。
使用requestIdleCallback浏览器空闲时间进行计算
async function calculateHashIdle() { return new Promise(resolve => { const spark = new self.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 wookLoop = async deadline => { while (count < chunks.length && deadline.timeRemaining() > 1) { // 空闲时间,有任务 await appendToSpark(chunks[count].file) count++ if (count < chunks.length) { } else { resolve(spark.end()) } } window.requestIdleCallback(wookLoop) } window.requestIdleCallback(wookLoop) }) }
- 最终也可以快速不失卡顿的进行hash的计算。
抽样hash进行计算,hash值取前中后三块区域进行计算。前中后并且取2个字节进行计算,速度就会很快,但是安全性就会变低,酌情处理。
async function calculateHashSample() { return new Promise(resolve => { const spark = new self.SparkMD5.ArrayBuffer() const reader = new FileReader() const size = file.size const offset = 2 * 1024 * 1024 // 第一个2M,最后一个区块数据全要 let chunks = [file.slice(0, offset)] let cur = offset while (cur < size) { if (cur + offset >= size) { // 最后一个区块 chunks.push(file.slice(cur, cur + offset)) } else { // 中间区块 const mid = cur + offset / 2 const end = cur + offset chunks.push(file.slice(cur, cur + 2)) chunks.push(file.slice(mid, mid + 2)) chunks.push(file.slice(end - 2, end)) } cur += offset } // 中间的,取前中后各2个字节 reader.readAsArrayBuffer(new Blob(chunks)) reader.onload = e => { spark.append(e.target.result) resolve(spark.end()) } }) }
结语
上面通过三种不同的方式让我们在解决文件过大的时候hash值计算过慢造成浏览器卡顿的问题上有了解决方式。
使用webwork进行计算,需要单独使用hash文件进行后台计算。
使用requestIdleCallback进行计算,可以很好的利用浏览器的空闲时间进行计算(比较推荐)。
使用抽样hash进行计算的会比上面两种都快,但是由于不是全部计算安全性就比较低了,适用于一些对安全性要求比较低的需求。
转载自:https://juejin.cn/post/7094433322729734157