You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

启用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 11:31:05