第一百零一次闯荡江湖的无名游侠 - gin
Go标准库net/http对文件上传已经提供了非常完善的支持，而Gin框架在其基础上进一步封装，因此使用Gin开发文件上传功能时，只需要简单几行代码便可以实现，Gin框架支持单个文件与多个文件同时上传。使用原生net/http库实现文件上传我们首先看看实现一个HTTP服务器，提供文件上传功能的简单示例package main import ( "io" "io/ioutil" "log" "net/http" "github.com/julienschmidt/httprouter" ) const ( MAX_UPLOAD_SIZE = 1024 * 1024 * 20 //最大上传大小，50MB ) func main() { r := RegisterHandlers() http.ListenAndServe(":8080", r) // 开启一个http服务 } // 定义路由 func RegisterHandlers() *httprouter.Router { router := httprouter.New() router.POST("/upload", uploadHandler) return router } // 文件上传接口 func uploadHandler(w http.ResponseWriter, r *http.Request, p httprouter.Params) { r.Body = http.MaxBytesReader(w, r.Body, MAX_UPLOAD_SIZE) if err := r.ParseMultipartForm(MAX_UPLOAD_SIZE); err != nil { log.Printf("File is too big") return } file, headers, err := r.FormFile("file") if err != nil { log.Printf("Error when try to get file: %v", err) return } //获取上传文件的类型 if headers.Header.Get("Content-Type") != "image/png" { log.Printf("只允许上传png图片") return } data, err := ioutil.ReadAll(file) if err != nil { log.Printf("Read file error: %v", err) return } fn := headers.Filename err = ioutil.WriteFile("./video/"+fn, data, 0666) if err != nil { log.Printf("Write file error: %v", err) return } w.WriteHeader(http.StatusCreated) io.WriteString(w, "Uploaded successfully") }如上我们通过r.FormFile函数获取上传的文件对象，以及文件的相关信息。然后通过headers.Header.Get函数获取上传文件的类型，判断类型是否符合要求。接着，使用ioutil.ReadAll函数读取文件的内容，并将其存储在data变量中。然后，通过headers.Filename获取上传文件的文件名，并使用ioutil.WriteFile函数将文件内容写入到指定路径下的文件中。使用Gin实现文件上传单个文件上传FormFile()获取文件单文件上传使用gin.Context的FormFile()方法，该方法的值为POST请求中文件上传字段的名称： engine := gin.Default() engine.POST("/upload", func(c *gin.Context) { file, err := c.FormFile("file") }) engine.Run()SaveUploadedFile()保存到本地 调用gin.Context的SaveUploadedFile()方法可以将文件保存到某个目录下： dst := "./uploads/" + file.Filename c.SaveUploadedFile(file,"./uploadFile")设置缓冲区大小Go默认文件上传缓冲区为32M，当有大量文件上传时，服务器内存的压力会很大，因此可以通过MaxMultipartMemory属性来设置缓冲区大小： //8M engine.MaxMultipartMemory = 8 << 20限制文件大小上传文件时，不限制文件大小可以会导致服务存储空间暴涨，因为有必须限制上传文件大小： fileMaxSize := 4 << 20 //4M if int(file.Size) > fileMaxSize { c.String(http.StatusBadRequest, "文件不允许大小于4M") return }限制文件类型对文件类型，也可以进行限制： reader, err := file.Open() if err != nil { fmt.Println(err) return } b := make([]byte, 512) reader.Read(b) contentType := http.DetectContentType(b) if contentType != "image/jpeg" && contentType != "image/png" { c.String(http.StatusOK, "文件格式错误") return }在上面的代码中，我们读取文件的前512个字节，再调用http.DetectContentType()便可以获取文件的MIME值。完整示例 package main import ( "fmt" "log" "net/http" "github.com/gin-gonic/gin" ) func main() { engine := gin.Default() //8M engine.MaxMultipartMemory = 8 << 20 engine.POST("/upload", func(c *gin.Context) { file, err := c.FormFile("file") if err != nil { log.Println(err) c.String(http.StatusBadRequest, "文件上传失败") return } fileMaxSize := 4 << 20 //4M if int(file.Size) > fileMaxSize { c.String(http.StatusBadRequest, "文件不允许大小于32KB") return } reader, err := file.Open() if err != nil { fmt.Println(err) return } b := make([]byte, 512) reader.Read(b) contentType := http.DetectContentType(b) if contentType != "image/jpeg" && contentType != "image/png" { c.String(http.StatusOK, "文件格式错误") return } dst := "./uploads/" + file.Filename c.SaveUploadedFile(file, dst) c.String(http.StatusOK, fmt.Sprintf("'%s' 上传成功!", file.Filename)) }) engine.Run() }测试文件上传$ curl -F "file=@./1.jpg" -X POST "http://localhost:8080/upload" '1.jpg' 上传成功!多个文件上传MultipartForm()获取多个文件如果要上传多个文件，多次调用gin.Context的FormFile()方法也是可以的，但更好的方式是使用gin.Context的MultipartForm()方法： package main import ( "fmt" "log" "net/http" "github.com/gin-gonic/gin" ) func main() { engine := gin.Default() engine.POST("/uploadMul", func(c *gin.Context) { form, err := c.MultipartForm() if err != nil { log.Println(err) c.String(http.StatusBadRequest, "文件上传失败") return } files := form.File["upload"] for _, file := range files { fmt.Println(file.Filename) } c.String(http.StatusOK, fmt.Sprintf("%d files uploaded!", len(files))) }) engine.Run() }测试文件上传运行程序后，使用curl命令上传多个文件：$ curl -F "upload=@./1.jpg" -F "upload=@./2.jpg" -X POST "http://localhost:8080/uploadMul 2 files uploaded总结Go标准库net/http对文件上传已经提供了非常完善的支持，可以满足我们大部分需求，Gin框架在其基础做了封装，让我们使用起来更加方便迅速。————————————————原文链接：https://blog.csdn.net/qq_35716689/article/details/135989080