Skip to content

Commit dc798ba

Browse files
committed
MD5 碰撞可能导致不同内容被误判为同一文件
1 parent e94e1e9 commit dc798ba

File tree

1 file changed

+13
-3
lines changed

1 file changed

+13
-3
lines changed

server/service/example/exa_breakpoint_continue.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,21 @@ func (e *FileUploadAndDownloadService) FindOrCreateFile(fileMd5 string, fileName
2323
cfile.FileMd5 = fileMd5
2424
cfile.FileName = fileName
2525
cfile.ChunkTotal = chunkTotal
26-
27-
if errors.Is(global.GVA_DB.Where("file_md5 = ? AND is_finish = ?", fileMd5, true).First(&file).Error, gorm.ErrRecordNotFound) {
26+
// 检查是否存在已完成上传的文件(is_finish = true)
27+
// 同时使用 fileMd5 和 fileName 作为查询条件,确保文件唯一性
28+
// 原因:虽然 MD5 碰撞概率极低,但理论上仍可能发生(不同内容产生相同 MD5)
29+
// 同时使用 MD5 和文件名可以避免误匹配到错误的文件
30+
// 使用 errors.Is 判断是否为记录不存在的错误,这是 GORM 的标准做法
31+
// 好处:可以区分"记录不存在"和"其他数据库错误",逻辑更清晰
32+
if errors.Is(global.GVA_DB.Where("file_md5 = ? AND file_name = ? AND is_finish = ?", fileMd5, fileName, true).First(&file).Error, gorm.ErrRecordNotFound) {
33+
// 不存在已完成的文件,查找或创建未完成的文件记录
34+
// Preload("ExaFileChunk") 预加载关联的切片记录
35+
// 好处:一次查询获取文件信息和已上传切片列表,减少数据库查询次数
36+
// FirstOrCreate 如果找到则返回,找不到则创建,原子操作保证并发安全
2837
err = global.GVA_DB.Where("file_md5 = ? AND file_name = ?", fileMd5, fileName).Preload("ExaFileChunk").FirstOrCreate(&file, cfile).Error
2938
return file, err
3039
}
40+
3141
cfile.IsFinish = true
3242
cfile.FilePath = file.FilePath
3343
err = global.GVA_DB.Create(&cfile).Error
@@ -39,7 +49,7 @@ func (e *FileUploadAndDownloadService) FindOrCreateFile(fileMd5 string, fileName
3949
//@description: 创建文件切片记录
4050
//@param: id uint, fileChunkPath string, fileChunkNumber int
4151
//@return: error
42-
52+
·
4353
func (e *FileUploadAndDownloadService) CreateFileChunk(id uint, fileChunkPath string, fileChunkNumber int) error {
4454
var chunk example.ExaFileChunk
4555
chunk.FileChunkPath = fileChunkPath

0 commit comments

Comments
 (0)