大文件切片上传

秒是不用传,快传是接着传

  • 文件切片
  • 并发控制
  • 状态记录
文件切片

File.slice() 将大文件切分为若干小文件

上传与记录

并发上传这些切片,同时在前端缓存记录下哪些已上传成功

通知合并

所有切片上传完成后,前端发送一个请求通知后端,让后端把这些切片按顺序拼回一个完整的文件

文件切片与状态管理.js 复制代码
// 1、生成文件hash
const fileHash = await calculateFileHash(file); 
// 2、分片大小
const CHUNK_SIZE = 2 * 1024 *1024;

const chunks = [];
let start = 0;
// 3、分片操作
while (start < file.size) {
    const end = Math.min(start + CHUNK_SIZE, file.size);
    chunks.push({
        file: file.slice(start, end),
        index: chunks.length,
        start,
        end,
        hash: fileHash // 用于服务端校验
    });
    start = end;
}
// 4、从本地存储获取已上传的分片记录
const uploadChunks = JSON.parse(localStorage.getItem(fileHash) || '[]');
并发控制与断点续传.js 复制代码
// 5. 找出待上传的分片
const pendingChunks = chunks.filter(chunk => !uploadedChunks.includes(chunk.index));

// 6. 控制并发数(比如3个并发)
const CONCURRENCY = 3;
async function uploadWithConcurrency() {
  for (let i = 0; i < pendingChunks.length; i += CONCURRENCY) {
    const batch = pendingChunks.slice(i, i + CONCURRENCY);
    // 并发上传这一批
    await Promise.all(batch.map((chunk) => uploadChunk(chunk));
  }
}

// 7. 单个分片上传函数
async function uploadChunk(chunk) {
  const formData = new FormData();
  formData.append('file', chunk.file);
  formData.append('index', chunk.index);
  formData.append('hash', chunk.hash);
  formData.append('total', chunks.length); // 总分片数

  try {
    const res = await Request({
      url: 'https://your-api.com/upload/chunk',
      method: 'POST',
      data: formData,
      header: { 'Content-Type': 'multipart/form-data' }
    });

    if (res.data.success) {
      // 上传成功,记录到本地存储
      uploadedChunks.push(chunk.index);
      localStorage.setItem(fileHash, JSON.stringify(uploadedChunks));
      
      // 计算并更新进度
      const progress = (uploadedChunks.length / chunks.length) * 100;
      console.log(`上传进度: ${progress.toFixed(2)}%`);
    }
  } catch (error) {
    console.error(`分片 ${chunk.index} 上传失败:`, error);
    // 这里可以加入重试逻辑,例如重试3次
  }
}

// 8. 开始上传
uploadWithConcurrency().then(() => {
  // 所有分片上传完成,通知服务端合并
  Request({
    url: 'https://your-api.com/upload/merge',
    method: 'POST',
    data: {
      hash: fileHash,
      fileName: file.name,
      totalChunks: chunks.length
    }
  }).then(res => {
    console.log('文件上传成功!URL:', res.data.fileUrl);
    // 上传成功,清除本地记录
    localStorage.removeItem(fileHash);
  });
});

服务端要做的事

前端的工作如上,后端需要配合提供三个接口,这也是面试中常被问到的设计点 :

  1. /upload/chunk :接收单个分片。通常会以文件hash_分片索引的格式临时存储。
  2. /upload/check(可选):查询已上传的分片。前端启动时调用,快速实现"断点续传"和"秒传"。
  3. /upload/merge:所有分片完成后,后端将临时分片合并,生成最终文件。

💡 高级优化与面试加分项

当你把这套逻辑讲清楚后,能主动提出以下优化点,会让面试官眼前一亮:

  • 秒传 :在初始化上传前,先根据文件hash请求后端。如果文件已存在,直接返回成功,一秒完成 。
  • Web Worker :将计算文件hash这种CPU密集型任务放到Web Worker里执行,避免阻塞页面渲染 。
  • 本地存储选型 :小文件、少量记录用localStorage;大文件、复杂记录用IndexedDB 。
  • 暂停/恢复 :通过AbortController来取消进行中的请求,实现暂停功能。恢复时,只需重新调用上传逻辑,pendingChunks会自动过滤掉已上传的部分 。
相关推荐
ss27314 分钟前
AI全栈实战 | 3.5-01 Python 全栈前端最小集:不会 React 也能做出能看的后台,关键就一条线
前端·python·react.js
人工智能培训17 分钟前
数字孪生驱动大模型工业知识库:为具身机器人植入领域专业经验
大数据·linux·服务器·前端·人工智能
维克兜率天30 分钟前
【维克】通道突破:画出趋势的“轨道线“
前端·数据库·人工智能
Ai-_Man31 分钟前
从聊天框到正式文档:AI导出鸭瞄准AI大模型应用的“最后一公里”
开发语言·前端·javascript·人工智能·小程序
乌暮40 分钟前
拆解网页的底层逻辑:用费曼学习法讲透 HTML 与 CSS
前端·css·学习·html
陈随易10 小时前
bm2,Node.js 与 Bun 项目部署新选择
前端·后端·程序员
福兮说12 小时前
canvas 旋转图片的六个坑:四角被裁、Math.ceil 多出 1px 黑边、JPG 角发黑、翻转方向反了
前端·javascript·图像处理·canvas
传人once13 小时前
多图片上传预览功能如何写
前端·css·html·jquery·html5
Eric.4613 小时前
Wan‑Animate+MiniMax-H3 本地部署 AI 漫剧流水线:8G 显存动作迁移与动态分镜工程实战
前端·人工智能·comfyui·ai漫剧
库拉镜像AI牛牛15 小时前
短剧内容自动化生产:知漫剧工作室落地教程
大数据·服务器·前端·人工智能·语音识别