Go用http.HandleFunc接收文件需调用r.ParseMultipartForm设置MaxMemory,避免直接读r.Body;返回JSON须设Content-Type为application/json并用json.NewEncoder编码,错误时设状态码并返回含message的JSON。

Go怎么用http.HandleFunc接收上传的文件
Go标准库原生支持multipart/form-data解析,不需要额外依赖。关键在于调用r.ParseMultipartForm(不是ParseForm),否则r.MultipartForm为空,r.FormFile会返回http.ErrMissingFile。
常见错误是直接读r.Body或漏掉MaxMemory设置,导致大文件直接进磁盘临时目录,或小文件也写临时文件影响性能。
r.ParseMultipartForm(32 :建议设为32MB,既防内存爆,又避免小文件落盘(小于该值走内存)-
file, header, err := r.FormFile("file"):字段名必须和前端一致,大小写敏感 - 获取文件名用
header.Filename,但注意它可能被客户端篡改,不可直接拼路径 - 读取完记得
file.Close(),否则临时文件句柄不释放
怎么安全保存上传的文件到服务器
别直接用header.Filename做本地路径,这是典型路径遍历漏洞点。比如客户端传../../etc/passwd,不做处理就会写到系统关键位置。
更稳妥的做法是忽略原始文件名,生成唯一ID(如uuid.New().String()),再根据header.Header.Get("Content-Type")校验类型(比如只允许image/jpeg、application/pdf),最后用os.Create写入预设目录。
- 目标目录需提前
os.MkdirAll创建,并确认Web服务进程有写权限 - 写入前建议用
io.CopyN(dst, src, maxFileSize)限制最大写入量,防止恶意超大文件耗尽磁盘 - 如果要保留原始扩展名,可从
header.Header.Get("Content-Type")映射(如image/png → ".png"),而不是信任Filename
上传大文件时怎么避免请求超时或内存溢出
HTTP上传本身不提供断点续传,但Go服务端能通过控制解析行为缓解压力。默认http.Server没有读取超时,上传一个2GB文件卡住10分钟也不会中断,客户端早已断连。
必须显式配置ReadTimeout和MaxHeaderBytes,同时在ParseMultipartForm前加context.WithTimeout控制解析耗时。
-
http.Server{ReadTimeout: 30 * time.Second}:防止慢速上传长期占连接 -
r.ParseMultipartForm前用ctx, cancel := context.WithTimeout(r.Context(), 15*time.Second),超时就cancel()并返回408 Request Timeout - 真正的大文件(>100MB)建议前端分片上传,后端用
os.OpenFile(..., os.O_CREATE|os.O_APPEND)合并
怎么返回JSON响应而不是跳转或空白页
很多初学者用http.Redirect或没写Content-Type,导致前端收不到{ "success": true }。Go默认返回text/html,必须手动设头。
上传成功后,用w.Header().Set("Content-Type", "application/json; charset=utf-8"),再json.NewEncoder(w).Encode(map[string]interface{}{"url": "/uploads/xxx.jpg"})。
- 失败时别只
log.Println,要w.WriteHeader(http.StatusBadRequest)并返回带message字段的JSON,方便前端提示 - 如果前端用
fetch,注意它不会自动reject网络错误,需检查response.ok和response.status - 跨域场景下,确保
Access-Control-Allow-Origin已配,否则浏览器拦截响应体
文件上传看着简单,但Filename校验、Content-Type验证、超时控制、磁盘配额这四点,少一个都容易在线上出问题。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











