大文件分片上传与异步处理方案总结
核心结论:大文件分片上传 + 异步解析是一套后端架构模式,不是 Django 专属。Java/Spring Boot 完全能实现,且企业级场景更常用 Java。你之前写 Django 的经验大部分能迁移过来。
一、Django vs Java 实现对比
| 功能模块 | Django 实现 | Java 实现 |
| Web 框架 | Django REST Framework | Spring Boot + Spring Web |
| 分片接口 | DRF 4 个接口(check/chunk/progress/merge) | Spring MVC 写同样 4 个接口 |
| 临时存储 | MinIO / 本地临时目录 | MinIO Java SDK / 本地目录(完全一样) |
| 异步任务 | Celery + Redis | Spring @Async / RabbitMQ / Kafka 消费者 |
| 任务状态机 | DB 表 + Redis 幂等键 | 同样 DB 表 + Redis(Spring Data Redis) |
| 数据库/向量库 | PostgreSQL+PostGIS / Milvus | MyBatis/JPA 连同样的库,Milvus 官方 Java SDK |
选择建议:
- 自己的项目/求职作品 → 继续用 Django 最划算,DRF + Celery + Redis 生态最成熟,不用边学框架边踩坑。
- 公司要求 Java 或岗位要 Java 经验 → 值得转。业务逻辑(分片序号、MD5 去重、状态机)是同一套,迁移成本主要在框架语法和配置。
二、四个核心组件在项目中的作用
1. Redis —— 高速缓存、幂等、进度、限流
- 秒传 & 分片断点续传:存
文件MD5 → 是否已上传;租户ID:文件MD5 → 已上传分片编号集合
- 幂等控制:幂等键
文件MD5 + 任务ID,防止同一文件被重复投递、重复 OCR/向量入库
- 并发限流、信号量:控制同时跑多少个解析任务,防止 OOM
- 分布式锁:分片合并时加锁,防止多个请求同时合并同一文件
学习重点String/Set/Hash 数据类型、TTL 过期、分布式锁(Redisson)、SETNX 原子操作、RDB/AOF 持久化策略
2. RabbitMQ / Kafka —— 异步任务队列(替代 Celery)
文件合并成功后,HTTP 接口不能阻塞等待十几分钟的 OCR/解析/向量入库。MQ 把耗时任务从 HTTP 请求中解耦。
- RabbitMQ(推荐优先学):适合业务任务,支持重试、死信队列 DLX,和 Celery 最像,上手简单
- Kafka:高吞吐、大数据流,适合海量文件场景,但重试/死信机制比 RabbitMQ 麻烦
学习重点消息 ACK 机制、NACK 重试、死信队列、消息幂等、队列限流;消息体只传元数据(MD5、MinIO路径、租户ID、任务ID),不传文件二进制
3. MyBatis —— Java 操作数据库(对应 Django ORM)
- 文件主表:租户、文件名、MD5、文件大小、MinIO 存储路径、上传时间
- 任务状态表:状态机(pending / processing / success / failed)、重试次数、失败原因、进度
- 结构化解析结果:PostGIS 空间数据
学习重点Mapper/XML 注解、@Transactional 事务、批量操作、长事务避免;Redis 只放临时/热点数据,最终业务数据必须入库
Django 对照:Celery ≈ RabbitMQ/Kafka + Redis(Celery 本身就是用消息队列做任务,Redis 当结果/缓存);Django ORM ≈ MyBatis
三、系统架构图
flowchart LR
subgraph Client["客户端 浏览器前端"]
F1[MD5预计算 & 秒传检测]
F2[大文件分片 5MB/片]
F3[并行分片上传]
F4[查询进度/任务状态]
end
subgraph SpringBoot["SpringBoot 应用服务
MyBatis + Redis集成"]
API["REST接口层
/check /chunk /progress /merge /task/status"]
REDIS[(Redis
-分片上传进度集合
-秒传MD5标记
-分布式锁(分片合并)
-任务幂等键、并发限流信号量)]
DB[(PostgreSQL + PostGIS
MyBatis持久化
文件元数据表|任务状态表
状态机:pending/processing/success/failed)]
end
subgraph Storage["对象存储 MinIO"]
BucketTmp[临时桶:存储文件分片]
BucketFinal[正式桶:合并后的完整大文件]
end
subgraph MQ["RabbitMQ 消息队列(异步任务)"]
TaskQueue[文件解析任务队列]
DLQ[死信队列|重试耗尽任务]
end
subgraph Consumer["独立解析消费服务"]
Worker[任务消费者]
Parser[流式解析引擎
OCR/图纸解析/文本向量化]
Milvus[(Milvus向量数据库
文档向量存储与检索)]
end
F1 --> API
F2 --> F3 --> API
F4 --> API
API --> REDIS
API --> DB
API -->|分片二进制直传| BucketTmp
API -->|分片合并校验| BucketFinal
API -->|合并完成投递任务消息| TaskQueue
TaskQueue --> Worker
Worker -->|Redis幂等校验| REDIS
Worker -->|更新任务状态| DB
Worker -->|流式读取文件| BucketFinal
Worker --> Parser
Parser -->|结构化&空间数据入库| DB
Parser -->|向量化存储| Milvus
Worker -->|瞬时异常 NACK 指数退避重试| TaskQueue
Worker -->|重试耗尽/永久异常| DLQ
四、模块思维导图
mindmap
root((GB级大文件分片上传&异步解析系统))
客户端浏览器前端
MD5预计算 & 秒传检测
大文件分片(5MB/片)
并行分片上传
查询上传进度/任务状态
SpringBoot应用服务
REST接口层
/check 秒传校验
/chunk 分片上传
/progress 查询上传进度
/merge 分片合并
/task/status 查询解析任务状态
Redis缓存
分片上传进度集合
文件MD5秒传标记
分片合并分布式锁
任务幂等键、并发限流信号量
PostgreSQL+PostGIS
文件元数据表
任务状态表 pending/processing/success/failed
MinIO对象存储
临时桶:存放文件分片
正式桶:合并后完整大文件
RabbitMQ消息队列
文件解析任务队列
DLQ死信队列:重试耗尽失败任务
独立解析消费服务
任务消费者Worker
流式解析引擎
OCR识别
图纸解析
文档文本向量化
Milvus向量数据库
文档向量存储 & 向量检索
核心业务流程
前端分片上传 -> SpringBoot接口
分片落MinIO临时桶,Redis记录分片
全部分片完成,调用merge合并到正式桶
投递解析任务消息至RabbitMQ
消费端拉取任务,Redis幂等校验
流式读取文件,执行解析向量化
结构化数据入库PG,向量存入Milvus
容错机制
瞬时异常:NACK指数退避重试
永久失败:转入死信队列,人工排查
五、完整上传 + 异步解析时序图
sequenceDiagram
participant Front as 前端浏览器
participant SB as SpringBoot服务
participant Redis as Redis
participant MinIO as MinIO对象存储
participant MQ as RabbitMQ
participant Worker as 解析消费服务
participant PG as PostgreSQL+PostGIS
participant Milvus as Milvus向量库
Note over Front,Milvus: 阶段1:秒传预校验
Front->>SB: 1.上传前校验:文件MD5
SB->>Redis: 查询MD5是否已存在
alt 文件已存在(秒传命中)
Redis-->>SB: 返回已存在标记
SB-->>Front: 返回秒传成功,直接跳转任务查询
else 文件不存在
Redis-->>SB: 无记录,开始分片上传
SB-->>Front: 允许上传
Note over Front,Milvus: 阶段2:分片并行上传 & 断点续传
loop 多分片并行上传
Front->>SB: 上传分片(分片序号+MD5)
SB->>MinIO: 分片写入临时桶
SB->>Redis: 记录已接收分片编号
SB-->>Front: 返回分片上传成功
end
Front->>SB: 查询已上传分片 /progress(断点续传)
SB->>Redis: 获取已上传分片集合
SB-->>Front: 返回缺失分片列表,前端补传
Note over Front,Milvus: 阶段3:分片合并
Front->>SB: 请求合并分片 /merge
SB->>Redis: 获取分布式锁,防止并发合并
SB->>MinIO: 校验全部分片,合并为完整文件,移入正式桶
SB->>Redis: 释放合并分布式锁
SB->>PG: 写入文件元数据记录
SB->>MQ: 投递【文件解析任务】消息
SB-->>Front: 返回合并成功,返回taskId,前端轮询状态
Note over Front,Milvus: 阶段4:MQ消费,异步解析
MQ-->>Worker: 推送解析任务消息
Worker->>Redis: 幂等校验(MD5+taskId),防止重复解析
alt 任务未处理
Worker->>PG: 更新任务状态 pending → processing
Worker->>MinIO: 流式读取完整文件(不加载全文件入内存)
Worker->>Worker: 流式OCR、图纸解析、文本向量化
alt 解析成功
Worker->>PG: 事务提交结构化/空间数据
Worker->>Milvus: 写入文档向量
Worker->>PG: 更新任务状态 processing → success
Worker-->MQ: ACK确认,任务完成
else 瞬时异常(可重试)
Worker-->MQ: NACK,消息重回队列,指数退避重试
else 致命异常(不可重试)
Worker->>PG: 更新任务状态为failed,记录错误信息
Worker-->MQ: 消息转入死信队列DLQ
end
else 任务已处理(幂等命中)
Worker-->MQ: ACK,直接跳过解析
end
Note over Front,Milvus: 阶段5:前端轮询查询任务结果
loop 前端轮询
Front->>SB: 查询任务状态 /task/status(taskId)
SB->>PG: 查询任务状态
SB-->>Front: 返回状态、进度、失败原因
end
end
六、简历项目描述(可直接复制)
基于 SpringBoot 搭建 GB 级大文件分片上传与异步解析平台,集成 MinIO 实现分片临时存储与文件持久化;利用 Redis 实现秒传检测、断点续传、分片合并分布式锁与任务幂等控制;RabbitMQ 作为任务队列解耦耗时 OCR/图纸解析流程,通过死信队列处理任务失败重试;MyBatis 操作 PostgreSQL+PostGIS 存储文件元数据与地理结构化信息,解析文档向量存入 Milvus 向量库。任务采用状态机管理,结合数据库事务保证数据一致性,支持租户隔离、并发限流,防止大文件处理引发 OOM。
核心技术点清单
- 缓存和数据库的职责分离:Redis = 临时热点;DB = 持久化
- MQ 异步解耦:HTTP 请求不阻塞耗时任务
- 消息可靠性三件套:ACK、死信、重试 + 幂等(MQ + Redis)
- 分布式锁场景:分片合并
- 任务状态机 + 事务保证最终一致性
- 流式读取文件,不整体载入内存,防止 OOM