H5 大文件分片上传设计

举报
yd_290101916 发表于 2026/10/10 09:56:10 2026/10/10
【摘要】 H5 大文件分片上传设计大文件一次性上传容易受弱网、页面切换和服务超时影响。分片上传把文件切成小块,允许有限并发、失败重试和断点续传。但它需要服务端共同定义文件标识、分片校验、合并顺序和过期清理,不能只由前端切割文件就保证可靠。 一、选择文件并尽早校验<label for="file-input">选择文件</label><input id="file-input" type="file"...

H5 大文件分片上传设计

大文件一次性上传容易受弱网、页面切换和服务超时影响。分片上传把文件切成小块,允许有限并发、失败重试和断点续传。但它需要服务端共同定义文件标识、分片校验、合并顺序和过期清理,不能只由前端切割文件就保证可靠。

一、选择文件并尽早校验

<label for="file-input">选择文件</label>
<input id="file-input" type="file">

选择后先检查业务允许的大小、类型和数量。前端校验用于及时反馈,服务端仍必须独立校验,不能信任浏览器提供的文件名和类型。

二、按固定大小切片

type FileChunk = {
  index: number;
  start: number;
  end: number;
  blob: Blob;
};

function splitFile(file: File, chunkSize: number): FileChunk[] {
  const chunks: FileChunk[] = [];

  for (let start = 0, index = 0; start < file.size; start += chunkSize, index += 1) {
    const end = Math.min(start + chunkSize, file.size);
    chunks.push({
      index,
      start,
      end,
      blob: file.slice(start, end)
    });
  }

  return chunks;
}

分片过小会增加请求数量,过大则失败重传成本高。大小应根据网络、服务限制和设备内存测量。

三、建立稳定上传会话

开始上传时,客户端向服务端提交文件元数据,获得稳定会话标识。后续每个分片携带:

  • 上传会话标识。
  • 分片序号和总数。
  • 当前分片大小。
  • 文件整体或分片校验值。

服务端使用会话隔离不同文件,并拒绝不符合约定的序号和大小。

四、控制并发数量

同时上传所有分片会占满网络和内存。可以使用固定工作池:

async function uploadWithConcurrency(
  chunks: readonly FileChunk[],
  concurrency: number,
  upload: (chunk: FileChunk) => Promise<void>
): Promise<void> {
  if (!Number.isInteger(concurrency) || concurrency <= 0) {
    throw new Error('并发数量必须为正整数');
  }

  let nextIndex = 0;

  async function worker(): Promise<void> {
    while (nextIndex < chunks.length) {
      const chunk = chunks[nextIndex];
      nextIndex += 1;
      await upload(chunk);
    }
  }

  const workers = Array.from(
    { length: Math.min(concurrency, chunks.length) },
    () => worker()
  );
  await Promise.all(workers);
}

并发参数必须大于零,并根据移动网络表现设定合理上限。

五、进度按字节计算

分片完成数量不能准确代表进度,因为最后一片大小可能不同,进行中的分片也已有传输量。

function calculateProgress(
  uploadedBytes: number,
  totalBytes: number
): number {
  if (totalBytes === 0) return 1;
  return Math.min(1, uploadedBytes / totalBytes);
}

多个并发分片的已传字节需要按分片分别记录,不能把重复进度事件累加两次。

六、只重试合适错误

短暂断网和服务繁忙可以按有限次数重试;文件不合法、会话过期和权限拒绝重复上传也不会成功。

重试应带退避间隔,并支持用户取消。分片操作要幂等,相同会话和序号重复到达时不能写入两份数据。

七、断点续传查询服务端状态

页面恢复后,不能只相信本地记录哪些分片成功。应查询服务端已确认分片集合,再上传缺失部分。

浏览器出于安全原因不会在重新打开页面后自动恢复文件对象,通常仍需要用户重新选择同一文件,并通过大小、名称和内容校验确认一致。

本地只保存非敏感会话元数据,并设置过期清理。

八、完成合并要独立确认

所有分片上传成功后,客户端发起完成命令。服务端校验总数、顺序和整体内容后合并,并返回最终文件标识。

前端只有收到完成确认后才能显示上传成功。分片全部传输结束不等于服务端已经生成可用文件。

九、取消与清理

用户取消时应停止在途请求,并通知服务端废弃会话。服务端还需要定期清理长时间未完成的临时分片。

组件销毁是否取消上传由产品决定。需要跨页面继续时,应把任务提升到应用级管理器,并保留可观察进度,而不是让页面对象长期存活。

十、安全检查

服务端必须验证文件内容、大小、分片数量和最终用途。文件名不能直接作为存储位置,预览与下载时也要设置正确内容处理策略。

日志只记录会话标识、分片序号和错误阶段,不输出用户文件内容。

总结

分片上传是前后端共同协议。固定边界切片,控制并发,按字节汇总进度,以幂等分片支持有限重试,再由服务端确认断点和最终合并。取消、过期和临时数据清理同样属于完整上传生命周期。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。