RAG文件分片上传

文件上传流程

controller层

  • 前端会对文件先进行MD5计算出唯一标识,再进行分片向后端发出分片上传的请求
  • 在每个文件第一个分片的时候要进行验证,截取文件的扩展名,验证改文件类型是否支持
  • 如果文件没有所属的组织标签,那么就获取该用户的主组织标签,并设置这个文件所属组织

Service层

  • 先查询mysql数据库中 file_update 表是否存在这个文件 MD5 标识,查询是 file_MD5 + usrId 一起查询,如果不存在就创建
  • 双层校验:第一层:检查Redis(或其他缓存)中是否标记该分片已上传,第二层:检查数据库(chunk_info表)中是否有该分片的记录
  • 处理 “分片已上传(在 redis 中存在)但数据库无记录” 的异常场景
  • 分片实际上传到 MinIO(核心操作),并且在 Redis 中标记分片已上传
  • 补充分片信息到数据库(chunk_info 表)

前端对文件进行分片

  • 前端使用 MD5 算法把文件的二进制数据转换成32位字符串,作为这个文件的唯一标识。
  • 还有 SHA-256 算法成长64位字符串,安全性远高于 MD5 算法。但是相比于 MD5 计算速度有所下降,并且 64 位存储空间也需要更大
  • 在对文件进行分块的时候是按照 5MB 进行分块的, 这个 5MB 是最佳实践数值。主流浏览器和后端服务器对于单次 Post 请求表单数据大小有默认限制, 5MB 低于大多数中间件的安全阈值,同时避免分块过小导致 TCP 握手次数增多, 5MB 也能正好利用 TCP 拥塞窗口。前段浏览器在读取分块的时候会加载到内存, 5MB 可以实现多路(3 ~ 5 路)并行上传。 5MB 不是固定值,可以根据实际网速,文件大小进行相关的调整

合并文件

  • 前端传入辅助类(包含文件名和 file_md5)+ userId
  • 检查文件完整性,是否在 file_upload 中存在,根据 userId 和 file_md5 查询
  • 先在 controller 层检查文件是否完整上传。一个方法传入 userId 和 filemd5 在 file_upload 中查询到文件的大小,再通过分割时候的大小 5MB 计算出来应该有多少个分片,再从 redis中查询,先获得 bitmap 转换成字节数组,循环遍历位数为 1 的添加到 List 数组中,最后比较数组大小和应该有多少个分片,这个是粗略的比较,如果小于预期分片数,就先直接报错返回。
  • 合并文件
    • 进行更准确比较,已上传分片数必须等于预期分片数
    • 检查 MiNIO 中每个分片是否存在。在 chunk_info 数据库表中有记录每个分片的存储路径 storage_path。根据 userId 和 file_md5 查到分片集合,再从分片集合中提取出来路径 String集合
    • 在这里我发现一个问题,原始代码使用的合并路径是 "merged/" + fileName, 但是有可能产生路径冲突,所以添加 UUID 或者时间戳都可以
    • 把文件路径转换成 ComposeSource 对象,包含桶以及存储对象
    • 合并文件完成之后开始循环遍历路径清理 MinIO 存储的分片,清除 Redis 的 bitmap 状态,更改数据库 file_upload 表中上传状态 0 变成 1,表示上传成功
    • 生成预签名 URL 并返回,过期时间为 1 个小时,在这个期间可以凭借这个这个 URL 从 MinIO 中获取合并后的文件
  • 向 Kafka 发送任务。构建了 FileProcessingTask 类,包括文件md5,文件名,用户名 ,预签名等。
posted @ 2026-01-26 17:57  Huangyien  阅读(6)  评论(0)    收藏  举报