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

Golang使用multipart.Part读取文件时随机出现unexpected EOF错误排查

多文件上传时io.Copy返回unexpected EOF的问题分析

问题根源

代码存在两个关键错误:

  1. 变量遮蔽导致文件句柄未正确关闭
    你先声明外层var outfile *os.File,紧接着执行defer outfile.Close()——此时outfile还是nil。后续os.Create时使用outfile, err := ...,这里的outfile是局部变量,覆盖了外层同名变量,导致外层outfile始终为nil,defer的是空指针的Close操作,实际打开的文件句柄根本没被延迟关闭。
  2. 文件描述符耗尽
    上传大量文件时,未关闭的文件句柄会耗尽系统允许的文件描述符上限,后续IO操作就会抛出unexpected EOF错误。而使用r.ParseMultipartForm时,Go标准库会自动管理临时文件和文件描述符,因此不会出现该问题。

修复后的代码

// Error handling not complete
func (t *Tools) UploadFiles(r *http.Request, uploadDir string) {
    reader, err := r.MultipartReader()
    if err != nil {
        return
    }
    for {
        part, err := reader.NextPart()
        if err == io.EOF {
            break
        }
        if err != nil {
            return
        }

        fileName := part.FileName()
        outfile, err := os.Create(filepath.Join(uploadDir, fileName))
        if err != nil {
            _ = part.Close() // 创建文件失败时关闭当前part
            return
        }
        defer outfile.Close() // 将defer放到文件创建成功后,避免变量遮蔽

        fileSize, err := io.Copy(outfile, part)
        log.Printf("Size: %d FileName: %s Error: %v\n", fileSize, fileName, err)
        if err != nil {
            _ = outfile.Close() // 出错时主动关闭文件
            _ = part.Close()
            return
        }
        // 主动关闭part,释放资源
        if err := part.Close(); err != nil {
            log.Printf("Close part error: %v\n", err)
        }
    }
}

额外注意点

  • 处理完每个part后要主动调用part.Close(),避免持有不必要的资源。
  • 完善错误处理逻辑,比如创建文件失败时,要及时关闭当前part防止资源泄漏。

内容的提问来源于stack exchange,提问作者Nathan Brandt

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 13:03:16