必须用io.copy流式计算md5,不能将整个文件读入[]byte;需每次请求独立创建md5.new()实例,调用file.open()获取reader后写入hash.hash,再hex.encodetostring(h.sum(nil))获取32字符哈希值。

Go 用 echo.Context 读取文件流时,不能直接用 md5sum 命令
因为 echo.Context 的 c.FormFile() 或 c.MultipartForm() 返回的是内存或临时磁盘上的 *multipart.FileHeader,不是已落地的文件路径。你没法把路径丢给系统命令。必须在 Go 运行时用 io.Copy 或分块读取,边读边喂给 hash/md5。
md5.Sum([]byte) 不适合大文件,得用 hash.Hash 接口流式计算
直接把整个文件读进 []byte 再传给 md5.Sum,对几十 MB 以上的文件会触发 OOM。正确做法是获取文件的 io.Reader(比如 file.Open() 或 fh.Open()),然后用 io.Copy 把它写入一个 hash.Hash 实例:
file, err := c.FormFile("file")
if err != nil {
return err
}
src, err := file.Open()
if err != nil {
return err
}
defer src.Close()
h := md5.New()
if _, err := io.Copy(h, src); err != nil {
return err
}
fileMD5 := hex.EncodeToString(h.Sum(nil)) // 得到 32 字符 hex 字符串
上传 XML 或文本内容时,Content-MD5 校验失败的常见原因
如果你在 Echo 中处理的是原始 body(比如 c.Request().Body),而不是表单文件,那要注意:HTTP body 可能已被提前读取(例如中间件调用了 c.Request().Body),再次读会返回空。此时必须用 c.Request().GetBody() 重置,或者在读取前先 io.Copy(ioutil.Discard, ...) 消耗并缓存。
Echo框架 5.1.0 版本源码包下载,适合关注 RealIP 行为变化、StartConfig.Listener、NewDefaultFS 和观测性中间件入口的开发团队。
- XML 内容必须用原始字节计算 MD5,不能先
xml.Unmarshal再序列化——编码、缩进、换行符(\nvs\r\n)、BOM 都会导致哈希不一致 - 如果前端用
fetch发送 raw string,后端用io.ReadAll(c.Request().Body),要确保没被其他中间件提前消费 - 生成
Content-MD5头时,需 Base64 编码原始 MD5 二进制值:base64.StdEncoding.EncodeToString(h.Sum(nil)),不是 hex 字符串
并发上传多个文件时,md5.New() 必须每个请求独立创建
hash.Hash 实例不是 goroutine 安全的,也不能复用。常见错误是把 md5.New() 提到全局变量或中间件外层,结果多个请求写同一个 hash 实例,MD5 值错乱。每次处理文件都应:
- 调用
md5.New()新建实例 - 用
io.Copy流式写入 - 立刻调用
h.Sum(nil)获取结果,不要缓存h
真正容易被忽略的是:文件打开后忘记 defer src.Close(),导致句柄泄漏;还有没检查 io.Copy 的返回 error,让校验通过了但实际只读了一半数据。










