☰
上传 2GB 的视频进知识库,为什么不能一次 POST?
2026/10/10 12:14:14 网站建设 项目流程

上传一个 2GB 的培训视频,进度条走到 73%,Wi-Fi 突然断了。

刷新页面,上传进度归零。

已经传了约 1.5GB,为什么还要从头再来?

如果采用整文件 POST 上传,没有额外的断点恢复机制,连接中断后通常只能重新发送整个文件。

文件越大,失败的成本越高。尤其在文档管理和知识库系统中,培训录像、会议录音、打包资料可能达到几百 MB,甚至几个 GB。

大文件上传真正需要解决的,不只是如何传输,而是中断后如何恢复。

在有谷大脑的文件上传链路中,我们采用了分片上传与断点续传方案:

5MB 分片上传 + Redis 记录状态 + MinIO 存储文件。

通过将文件拆成独立分片,并把上传状态与文件存储分离,让网络中断后的上传任务能够继续执行,而不必重新传输整个文件。

一、把 2GB 文件拆成 400 多个分片

核心思路是:不再一次传输完整文件,而是把它拆成多个可以独立上传的小文件。

整个上传过程分为四步:

init → chunks → progress → merge

  • init:初始化上传任务,返回uploadId和分片配置信息。
  • chunks:前端通过file.slice()切分文件,并发上传分片。
  • progress:查询服务端已经成功保存的分片索引。
  • merge:检查分片是否完整,再执行文件合并或对象组装。

为什么选择 5MB?

分片太大,失败后重传成本较高;分片太小,又会增加请求数量和管理开销。

5MB 可以作为一个起点,但不是所有场景下的最优值,实际还需要结合网络环境、对象存储接口和并发策略进行调整。

以 2 GiB 文件为例,按 5 MiB 切分,大约需要 410 个分片。

这样,即使某个分片上传失败,也只需要重新上传对应的分片,而不是整个文件。

二、Redis + MinIO,解决跨实例上传问题

分片上传还有一个容易忽略的问题:

上传到一半,请求被转发到了另一台服务器怎么办?

在多实例部署环境中,如果上传状态只保存在某个 API 进程的内存里,请求切换实例后,可能无法恢复之前的上传任务。

解决思路是将上传状态和实际文件分开管理:

  • Redis:记录uploadId、用户或任务关联信息、分片状态及上传任务状态。
  • MinIO:存储已经上传的分片或分片对应的对象数据。
  • API 服务:负责权限校验、分片接收、状态查询及合并流程。

这样,不同 API 实例可以访问同一份任务状态和对象数据,不必依赖单台服务器的内存。

不过,这里还有一个关键细节:

Redis 中记录“上传成功”,不等于文件一定已经可靠保存。

更稳妥的做法是先确认分片写入对象存储成功,再更新对应的上传状态。

如果状态更新失败,还需要通过对象存储中的实际分片信息进行核对,避免出现状态与文件不一致的问题。

因此,断点续传不仅要记录进度,还要保证上传状态能够与真实存储结果对应。

三、网络断了,怎么接着传?

假设一个 2GB 文件上传到 73% 时断网。

网络恢复后,前端可以按照以下流程恢复:

  1. 找回之前的uploadId。
  2. 调用progress查询已完成的分片。
  3. 对比本地分片列表,只上传缺失部分。
  4. 确认所有分片完成后,调用merge。

如果只是网络短暂中断,前端可以在原上传任务中继续重试。

如果页面已经刷新,则需要恢复上传任务信息;必要时让用户重新选择原文件,并验证文件身份,避免将不同文件的分片混在一起。

这里还有两个重要问题。

第一,分片上传需要具备幂等性。

例如第 10 个分片已经写入成功,但响应在网络中丢失,前端可能再次上传第 10 个分片。

服务端应当识别相同上传任务和分片索引,避免重复请求造成状态异常。

第二,merge 不能简单地把所有请求都当成新任务。

如果用户重复点击完成,或者网络重试导致多次调用merge,服务端需要通过任务状态控制、并发保护等机制,避免重复合并。

对于已经完成的任务,应返回已有结果,而不是再次创建完整文件。

断点续传的关键,不是记住进度条走到了哪里,而是准确知道哪些分片已经成功保存。

四、上传完成,不等于知识库已经可以检索

对于普通文件存储系统,文件上传成功可能意味着任务已经结束。

但在知识库系统中,上传完成通常只是第一步。

文件进入对象存储后,还可能需要经过:

内容解析 → OCR(按需)→ 文本切块 → 向量化 → 索引写入

这些任务的耗时与文件类型、内容规模以及处理资源有关,可能远长于上传本身。

因此,可以把文件上传和知识库入库拆成两个相对独立的阶段。

第一阶段:文件上传

负责分片传输、断点续传、文件完整性校验及对象存储。

第二阶段:知识库入库

在文件上传完成后创建或更新文档任务,通过 Celery 等异步任务框架执行解析、切块和索引构建。

如果需要向前端实时展示处理状态,可以通过 SSE 推送各阶段的进度事件。

这里需要区分两个概念:

  • 上传进度:文件已经成功传输了多少。
  • 入库进度:文件内容已经处理到哪个阶段。

二者不应混为同一个百分比。

这种设计还有一个好处:

如果后续文档解析或向量化失败,可以单独重试入库任务,不必重新上传整个文件。

五、还需要考虑哪些异常情况?

分片上传能够解决网络中断后的重复传输问题,但要在实际业务中稳定运行,还需要考虑几个边界条件。

1. 分片完整性校验

不能仅凭分片索引判断文件是否完整。必要时可以结合分片大小、校验和及最终文件校验,检测缺失或损坏的数据。

2. 过期任务清理

用户可能上传到一半就关闭页面。长期保留未完成的任务,会造成 Redis 状态和对象存储空间持续占用。

因此,需要为未完成任务设置清理策略。

3. 并发上传控制

并发越高不代表速度越快。过高的并发可能造成带宽竞争、连接数增加和服务端压力上升。

实际实现时,需要根据网络情况与服务端容量设置并发上限。

4. 合并失败恢复

合并过程中可能发生超时、进程退出或存储异常。

服务端应当明确区分上传中、待合并、合并中、已完成和失败等状态,避免任务长时间停留在无法恢复的中间状态。

写在最后

大文件上传并不只是把一个文件拆成多个小文件。

真正需要解决的是:网络中断后如何恢复、不同服务实例如何共享状态、重复请求如何处理,以及文件合并失败后如何重试。

Redis 负责协调上传状态,MinIO 负责保存文件数据,API 服务负责校验和流程控制。

断点续传的核心不是让进度条继续走,而是让已经成功传输的数据不必重复上传。

对于知识库系统,还需要进一步区分文件上传与内容入库,让传输失败和处理失败能够分别恢复。

这也是有谷大脑在设计文件上传链路时关注的问题:不仅要让文件成功上传,还要让上传过程可恢复、任务状态可追踪,并为后续知识库处理提供可靠的文件基础。

如果想进一步了解这些能力在产品里的实际应用,可以体验:

了解更多:https://brain.yogu.pro

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询