webworker-大文件上传
提示
提示:打开控制台查看分片结果
webworker
webworker 是浏览器提供的一种可以在后台运行 JavaScript 代码的技术,它可以在不阻塞主线程的情况下执行耗时操作,比如文件上传、数据处理等。
webworker 的使用非常简单,只需要创建一个 worker 对象,然后向它发送消息,worker 就可以在后台执行代码,并返回结果。
注意
- 原生 js 可以使用 new Worker
javascript
const worker = new Worker("./worker.js", {
type: "module",
});
- 在 vue 中使用需要使用
import Worker from "*.js?worker";
javascript
import Worker from "./worker.js?worker";
const worker = new Worker();
分片上传
分片上传是将一个大文件分成多个小文件,然后逐个上传,最后合并。这样可以避免一次性上传大文件导致的网络超时或内存溢出等问题。
分片上传的关键在于如何确定分片的大小和数量,以及如何合并分片。一般来说,分片大小可以根据网络带宽和文件大小来动态调整,数量则可以根据分片大小和文件大小来计算。
webworker 分片上传
cutFile 用于分片
js
import Worker from "./worker.js?worker";
const CHUNK_SIZE = 1024 * 1024 * 5; // 5MB
let THREAD_COUNT = 4;
if (typeof window !== "undefined") {
if (navigator.hardwareConcurrency) {
THREAD_COUNT = navigator.hardwareConcurrency;
}
}
const chunkList = [];
export const cutFile = async (file) => {
return new Promise((resolve, reject) => {
const chunkCount = Math.ceil(file.size / CHUNK_SIZE);
let chunkIndex = 0;
for (let i = 0; i < THREAD_COUNT; i++) {
const worker = new Worker();
worker.postMessage({
file,
index: i,
chunkSize: CHUNK_SIZE,
});
worker.onmessage = (e) => {
chunkIndex++;
chunkList.push(e.data);
if (chunkIndex >= chunkCount) {
worker.terminate(); // 结束worker
resolve(chunkList);
}
};
worker.onerror = (e) => {
reject(e);
};
}
});
};
createChunk 用于创建分片
js
import SparkMD5 from "./spark-md5.min.js";
export function createChunk(file, index, chunkSize) {
return new Promise((resolve, reject) => {
const start = index * chunkSize;
const end = start + chunkSize;
const spark = new SparkMD5.ArrayBuffer();
const fileReader = new FileReader();
const blob = file.slice(start, end);
fileReader.onload = function (e) {
spark.append(e.target.result);
const hash = spark.end();
resolve({
start,
end,
index,
hash,
chunk: blob,
});
};
fileReader.readAsArrayBuffer(blob);
});
}
worker webWorker
js
import { createChunk } from "./createChunk.js";
onmessage = async function (e) {
try {
const { file, index, chunkSize } = e.data;
const proms = [];
const chunk = createChunk(file, index, chunkSize);
proms.push(chunk);
const chunks = await Promise.all(proms);
postMessage(chunks);
} catch (error) {
postMessage({ error: error.message, md5: window.SparkMD5 });
}
};