跳转到主内容
极星编程网:以代码为星,赴技术山海!

如何在Golang中上传文件到服务器_Golang net/http multipart方法实践

必须用 multipart.Writer 构造请求体:创建 bytes.Buffer,用 multipart.NewWriter 写字段和文件,调用 w.Close(),设置 req.Header.Set("Content-Type", w.FormDataContentType())。 用
http.Post
上传文件会失败,必须用
multipart.Writer
直接调用
http.Post
并传入
bytes.NewReader
是行不通的——它只会把原始 字节 当纯文本发过去,服务器端收不到
multipart/form-data
的边界(boundary)和字段结构。正确做法是手动构造 multipart 请求体。 关键点在于:先创建
bytes.Buffer
,再用
multipart.NewWriter
写入字段和文件数据,最后把
Buffer.Bytes()
作为请求体发送,并设置正确的
Content-Type
头(含 boundary)。
multipart.Writer
会自动生成并管理 boundary,不能硬 编码 写完所有字段后必须调用
w.Close()
,否则 boundary 结尾缺失,服务端解析失败
req.Header.Set("Content-Type", w.FormDataContentType())
是必须的,不能手写
multipart/form-data; boundary=xxx
上传单个文件时如何设置文件名和字段名 服务端(比如 Gin 或标准
http.Request.ParseMultipartForm
)依赖
multipart.Writer.WriteField
和
multipart.Writer.CreateFormFile
的参数来识别字段名和文件元信息。字段名(
file
)、文件名(
report.pdf
)都由你控制,不是自动推断的。 常见错误是把文件内容当成字符串传给
WriteField
,结果服务端收到的是明文内容而非文件流。 立即学习 “ go语言免费学习笔记(深入) ”; php版微信js-sdk支付接口类 php版微信js-sdk支付接口类 下载 普通表单字段用
w.WriteField("username", "alice")
文件字段必须用
w.CreateFormFile("file", "report.pdf")
获取
io.Writer
,再把文件内容写进去 字段名(如
"file"
)要和服务端
r.FormFile("file")
中的键完全一致 上传多个文件或混合字段的完整示例
package main import ( "bytes" "io" "mime/multipart" "net/http" ) func uploadFiles() error { buf := &bytes.Buffer{} w := multipart.NewWriter(buf) // 写普通字段 if err := w.WriteField("project_id", "123"); err != nil { return err } // 写第一个文件 fw1, err := w.CreateFormFile("files", "a.txt") if err != nil { return err } io.WriteString(fw1, "content of a.txt") // 写第二个文件 fw2, err := w.CreateFormFile("files", "b.json") if err != nil { return err } io.WriteString(fw2, `{"id": 42}`) // 关键:关闭 writer,生成结尾 boundary w.Close() req, err := http.NewRequest("POST", "http://localhost:8080/upload", buf) if err != nil { return err } req.Header.Set("Content-Type", w.FormDataContentType()) client := &http.Client{} resp, err := client.Do(req) if err != nil { return err } defer resp.Body.Close() return nil }
注意:
CreateFormFile
的第一个参数是字段名(可复用,如都用
"files"
实现多文件),第二个是客户端看到的文件名(影响
Header.Get("Filename")
)。 服务端解析时容易忽略的边界条件 Go 标准库 要求在读取 multipart 前调用
r.ParseMultipartForm
,否则
r.MultipartForm
为
nil
。而且这个方法会一次性把全部文件读进内存或临时磁盘,不设限可能被恶意大文件打爆内存。 务必设置合理上限:
r.ParseMultipartForm(32 (32MB)
如果只处理小文件且想避免磁盘临时文件,可设
MaxMemory
,超过才落盘
r.MultipartForm.File["files"]
返回的是
[]*multipart.FileHeader
,不是单个值 读取文件内容前需用
header.Open()
获得
io.ReadCloser
,别漏掉
Close()
boundary 不匹配、没调
w.Close()
、服务端没调
ParseMultipartForm
——这三个问题占了调试失败的八成以上。

相关文章