启用MD5校验后,DO Spaces上传.ts/.m3u8文件变为0字节问题
问题原因分析
问题核心在于文件读取指针的位置:当你调用getMD5Hash(filePart)计算MD5时,会把文件的读取指针移动到文件末尾。之后直接将filePart作为PutObjectInput的Body参数时,指针已经停留在末尾,无法读取到任何内容,最终导致上传0字节的空文件。
至于MP4、JPEG文件看似正常,大概率是这类文件存在缓存残留或尺寸较小触发了隐性的指针重置,但这不是必然行为,本质上是代码逻辑的隐患,并非文件格式的问题。
修复方案
方案1:重置文件指针(推荐,适配大文件)
在MD5校验完成后,将文件指针重置到文件开头,确保后续上传能正常读取文件内容:
hashMD5 := getMD5Hash(filePart) // 重置文件指针到文件起始位置 if _, err := filePart.Seek(0, io.SeekStart); err != nil { fmt.Println("seek file error: " + err.Error()) c.String(http.StatusInternalServerError, "Internal server error") return } // 后续校验与上传逻辑保持不变 if c.Request.Header.Get("Hash-MD5") != hashMD5 { c.String(http.StatusBadRequest, "Bad file.") return }
方案2:读取文件到内存(适合小文件)
如果文件尺寸不大,可以先把文件内容读入内存,再分别用于MD5计算和上传,避免指针位置问题:
filePart, err := file.Open() if err != nil { fmt.Println("file: " + err.Error()) c.String(http.StatusBadRequest, err.Error()) return } defer filePart.Close() // 读取文件内容到内存 fileBytes, err := io.ReadAll(filePart) if err != nil { fmt.Println("read file error: " + err.Error()) c.String(http.StatusInternalServerError, "Internal server error") return } // 基于内存内容计算MD5 hashMD5 := getMD5Hash(bytes.NewReader(fileBytes)) // 校验逻辑 if c.Request.Header.Get("Hash-MD5") != hashMD5 { c.String(http.StatusBadRequest, "Bad file.") return } // 上传时传递内存中的文件内容 object := s3.PutObjectInput{ Bucket: aws.String("BUCKET_NAME"), Key: aws.String(file.Filename), Body: bytes.NewReader(fileBytes), ACL: aws.String("public-read"), }
额外代码优化建议
- 完善错误处理:当前代码中多处
err判断后未终止请求(比如c.FormFile出错后仍继续执行),容易引发后续panic,建议每个错误判断后都及时返回响应。 - 移除无用锁:函数内定义的
sync.Mutex lock是局部变量,每个请求都会创建新锁,完全起不到并发控制作用,应直接删除。
内容的提问来源于stack exchange,提问作者enesuzun
相关产品推荐
相关产品推荐

