使用 file.slice() 将文件按字节范围切分为多个小块,通过循环依次上传这些块。在每次上传前检查当前时间戳与任务起始时间的差值,若超过 50ms 则调用 requestanimationframe 或 settimeout 将剩余块的上传推迟到下一个事件循环,从而避免阻塞主线程。

如何确定每个分块的大小和总块数
根据文件的 size 属性和预设的 BLOCK_SIZE(例如 5MB)计算总块数。使用 Math.ceil 向上取整确保最后一块即使不足 BLOCK_SIZE 也能被处理。这种计算方式直接决定了后续切片操作的参数范围。

const FILE = { size: 1024 * 1024 * 10 }; // 10MB
const BLOCK_SIZE = 5 * 1024 * 1024; // 5MB
const TOTAL_BLOCKS = Math.ceil(FILE.size / BLOCK_SIZE);
console.log(TOTAL_BLOCKS); // 输出 2
如何在上传间隙插入非阻塞延时
在循环中维护一个起始时间戳,每次迭代前判断当前时间与起始时间的差值。如果差值大于阈值(如 50ms),说明当前宏任务执行时间过长,此时不立即执行下一次上传,而是将剩余工作放入 requestAnimationFrame 回调中。这样浏览器可以在渲染帧之间调度上传任务,保持 UI 响应。

async function uploadChunks(file, blockSize) {
const totalBlocks = Math.ceil(file.size / blockSize);
let startTime = performance.now();
const threshold = 50;
for (let i = 0; i threshold) {
await new Promise(resolve => requestAnimationFrame(resolve));
startTime = performance.now();
}
const start = i * blockSize;
const end = Math.min(start + blockSize, file.size);
const chunk = file.slice(start, end);
await uploadSingleChunk(chunk, i);
}
}
基于具体输入条件如何处理最后一块数据
当文件大小不是块大小的整数倍时,最后一块的结束索引由 Math.min(start + blockSize, file.size) 决定。这确保了最后一块只包含剩余的有效字节,不会越界读取。在实际调用 uploadSingleChunk 时,该块的数据完整性由浏览器底层保证,无需额外校验。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











