md5+文件大小是秒传最低可行组合,因单用md5有碰撞风险、单用大小更不可靠,二者组合在工程中能高效区分绝大多数重复文件,且计算成本低、兼容性好。

秒传不是“跳过上传”,而是服务端提前知道这个文件已经存在,直接跳过写入、返回已有路径。核心在于客户端和服务端用同一套哈希+大小组合做唯一标识,且服务端必须维护一个可查的哈希索引。
为什么MD5 + 文件大小是秒传的最低可行组合
单用MD5有碰撞风险(虽极低),单用文件大小更不可靠(大量小文件同尺寸)。两者组合在工程实践中足够区分绝大多数重复文件,且计算成本低、兼容性好。不建议用SHA256等高开销哈希——除非你明确需要抗强碰撞,否则纯属增加前端 CPU 和网络传输负担。
- 客户端必须在上传前计算完整文件的
MD5(不能只算前几KB) - 服务端索引表字段至少包含:
file_md5、file_size、storage_path、created_at - 查询条件必须是
WHERE file_md5 = ? AND file_size = ?,缺一不可
c.FormFile无法用于秒传校验,得用c.GetRawData
秒传发生在上传动作之前,用户点“上传”按钮后,前端应先发一个POST /api/quick-check请求,把md5和size发过来。这时候你根本没拿到*multipart.FileHeader,自然不能调c.FormFile——它只在真正收到multipart/form-data时才有效。
- 秒传接口应独立于上传接口,比如
POST /api/v1/quick-check - 用
c.ShouldBindJSON或c.Query接收参数,不要依赖FormFile - 若校验通过,直接返回
200 OK+ 已有url;失败则返回404,前端再走普通上传流程
秒传成功后,如何避免二次写入和路径冲突
秒传本质是“复用”,不是“复制”。一旦命中,服务端必须跳过所有保存逻辑,包括c.SaveUploadedFile、分片合并、临时目录清理等。但要注意两个坑:
- 不要直接返回原始
storage_path给前端——它可能是内部路径(如/data/uploads/xxx.jpg),需映射为可访问的 HTTP URL(如/files/xxx.jpg) - 如果业务要求记录“谁上传了该文件”,秒传场景下仍要插入一条关联记录(如
user_id、file_id、uploaded_at),但file_id指向的是已存在的文件条目 - 文件删除时,不能简单按
file_id删物理文件——得查引用计数,只有计数归零才真删
秒传看似只是加个哈希判断,实际牵扯到索引设计、URL 映射、引用管理、并发安全(多个用户同时秒传同一文件)——最容易被忽略的是:哈希索引没加联合唯一键,导致重复插入相同md5+size,后续查询就不可靠了。











