最近在帮朋友做一个健康数据记录的小项目,需要把用户的体检报告、运动记录这些文件传到服务器上。最开始想用PHP,后来干脆试了下Go语言,发现写起来挺顺手,代码也干净。
Go语言处理文件上传其实不复杂,核心就是利用net/http包里的功能。比如前端用户点“上传”按钮,选了个PDF格式的体检报告,后端就得接住这个文件,保存到指定目录里。
一个简单的上传接口
下面这个例子就能跑通整个流程。假设我们有个POST接口专门收文件,前端表单带一个叫file的字段:
package main
import (
"io"
"net/http"
"os"
)
func uploadHandler(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" {
err := r.ParseMultipartForm(10 << 20) // 最大支持10MB
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
file, handler, err := r.FormFile("file")
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
defer file.Close()
// 创建同名文件写入磁盘
f, err := os.OpenFile(handler.Filename, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer f.Close()
io.Copy(f, file)
w.Write([]byte("文件上传成功:" + handler.Filename))
return
}
// 返回上传页面
w.Write([]byte(`
<form method="post" enctype="multipart/form-data">
<input type="file" name="file"><br>
<input type="submit" value="上传">
</form>`))
}
func main() {
http.HandleFunc("/upload", uploadHandler)
http.ListenAndServe(":8080", nil)
}这段代码启动后访问http://localhost:8080/upload就能看到上传页面。选个文件提交,它就会存到程序运行的当前目录下。
实际使用时的一些小细节
真正上线肯定不能直接照搬上面的例子。比如文件名要避免冲突,可以加个时间戳或者UUID前缀;还要限制类型,别让人传个.exe上来。我后来给它加了个判断:
if !strings.HasSuffix(handler.Filename, ".pdf") &&
!strings.HasSuffix(handler.Filename, ".jpg") &&
!strings.HasSuffix(handler.Filename, ".xlsx") {
w.Write([]byte("只允许上传PDF、JPG、Excel文件"))
return
}还有就是路径问题,别把文件随便往根目录一扔,最好按日期分个文件夹,像uploads/2025-04/report.pdf这样,以后也好找。
现在这个小系统已经能稳定接收用户上传的健康资料了,配合定时备份,数据安全多了。Go语言虽然不是专做Web的,但这种轻量级任务干得很利索,写完基本不用怎么改。”}