使用mime/multipart上传文件报错:multipart: NextPart: EOF

go版本: go1.22.2

server文件:

Go 复制代码
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"time"
)

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("hello world"))
	})

	http.HandleFunc("/upload", func(w http.ResponseWriter, r *http.Request) {
		r.ParseMultipartForm(10 << 20) // 限制上传文件最大10M

		f, fh, err := r.FormFile("hello")
		fmt.Println("r.FormFile f: ", f)
		fmt.Println("r.FormFile fh: ", fh)
		fmt.Println("r.FormFile err: ", err)

		if err != nil {
			http.Error(w, "r.FormFile err: "+err.Error(), http.StatusBadRequest)
			return
		}

		filename := fmt.Sprintf("%d-hello.txt", time.Now().Unix())
		fw, err := os.OpenFile(filename, os.O_CREATE, 0666)
		if err != nil {
			fmt.Println("os.OpenFile err: ", err)
			http.Error(w, "os.OpenFile err: "+err.Error(), http.StatusBadRequest)
			return
		}

		_, err = io.Copy(fw, f)
		if err != nil {
			fmt.Println("io.Copy err: ", err)
			http.Error(w, "io.Copy err: "+err.Error(), http.StatusBadRequest)
			return
		}

		fw.Close()
		f.Close()

		w.Write([]byte("ok"))
		fmt.Fprint(w, "finished")
	})

	http.ListenAndServe(":8000", nil)
}

client文件:

Go 复制代码
package main

import (
	"bytes"
	"fmt"
	"io"
	"mime/multipart"
	"net/http"
	"os"
)

func main() {
	buf := bytes.Buffer{}
	wr := multipart.NewWriter(&buf)

	fieldname := "hello"    // 字段名
	filename := "hello.txt" // 文件名

	fw, err := wr.CreateFormFile(fieldname, filename)
	if err != nil {
		fmt.Println("wr.CreateFormFile err: ", err)
		return
	}

	fr, err := os.Open(filename)
	if err != nil {
		fmt.Println("os.Open err: ", err)
		return
	}

	_, err = io.Copy(fw, fr)
	if err != nil {
		fmt.Println("io.Copy err: ", err)
		return
	}

	// -----------------------
	// 创建form和发送请求在同一个函数中,如果这样写会,服务端报错:multipart: NextPart: EOF
	// defer wr.Close()
	// -----------------------
	fr.Close()
	wr.Close()
	// -----------------------

	// 发送请求
	link := "http://127.0.0.1:8000/upload"
	request, err := http.NewRequest(http.MethodPost, link, &buf)
	if err != nil {
		fmt.Println("http.NewRequest err: ", err)
		return
	}

	// 设置header
	request.Header.Set("Content-Type", wr.FormDataContentType())

	client := http.Client{}
	response, err := client.Do(request)
	if err != nil {
		fmt.Println("client.Do err: ", err)
		return
	}

	defer response.Body.Close()
	result, err := io.ReadAll(response.Body)
	fmt.Println(string(result), err)
}
Go 复制代码
# 报错信息
multipart: NextPart: EOF


# 上述代码说明
......

	// -----------------------
	// 创建form和发送请求在同一个函数中,如果这样写会,服务端报错:multipart: NextPart: EOF
	// defer wr.Close()
	// -----------------------
	fr.Close()
	wr.Close()
	// -----------------------

......

hello.txt文件:

Go 复制代码
hello world

执行文件:

Go 复制代码
# 服务端
go run server.go

# 客户端
go run client.go
相关推荐
却尘3 小时前
一篇小白也能看懂的 Go 字符串拼接 & Builder & cap 全家桶
后端·go
ん贤4 小时前
一次批量删除引发的死锁,最终我选择不加锁
数据库·安全·go·死锁
mtngt1117 小时前
AI DDD重构实践
go
Grassto2 天前
12 go.sum 是如何保证依赖安全的?校验机制源码解析
安全·golang·go·哈希算法·go module
Grassto4 天前
11 Go Module 缓存机制详解
开发语言·缓存·golang·go·go module
程序设计实验室5 天前
2025年的最后一天,分享我使用go语言开发的电子书转换工具网站
go
我的golang之路果然有问题5 天前
使用 Hugo + GitHub Pages + PaperMod 主题 + Obsidian 搭建开发博客
golang·go·github·博客·个人开发·个人博客·hugo
啊汉7 天前
古文观芷App搜索方案深度解析:打造极致性能的古文搜索引擎
go·软件随想
asaotomo7 天前
一款 AI 驱动的新一代安全运维代理 —— DeepSentry(深哨)
运维·人工智能·安全·ai·go
码界奇点8 天前
基于Gin与GORM的若依后台管理系统设计与实现
论文阅读·go·毕业设计·gin·源代码管理