Golang使用multipart.Part读取文件时随机出现unexpected EOF错误排查
多文件上传时io.Copy返回unexpected EOF的问题分析
问题根源
代码存在两个关键错误:
- 变量遮蔽导致文件句柄未正确关闭
你先声明外层var outfile *os.File,紧接着执行defer outfile.Close()——此时outfile还是nil。后续os.Create时使用outfile, err := ...,这里的outfile是局部变量,覆盖了外层同名变量,导致外层outfile始终为nil,defer的是空指针的Close操作,实际打开的文件句柄根本没被延迟关闭。 - 文件描述符耗尽
上传大量文件时,未关闭的文件句柄会耗尽系统允许的文件描述符上限,后续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
相关产品推荐
相关产品推荐

