Gin框架完全使用指南 | Gin框架文件上传

公众号:程序员读书,欢迎关注

在之前的文章中,我们讲解了在Gin框架中获取参数的几种方式,这几种方式获取的都是字符串,除了字符串,我们也可以获取客户端上传的文件。

Gin框架支持单个文件与多个文件同时上传。

单个文件上传

单文件上传使用gin.ContextFormFile()方法,该方法的值为POST请求中文件上传字段的名称:

css 复制代码
 engine := gin.Default()
 engine.POST("/upload", func(c *gin.Context) {
     file, err := c.FormFile("file")
 })
 engine.Run()

调用gin.ContextSaveUploadedFile()方法可以将文件保存到某个目录下:

css 复制代码
 dst := "./uploads/" + file.Filename
 c.SaveUploadedFile(file,"./uploadFile")

Go默认文件上传缓冲区为32M,当有大量文件上传时,服务器内存的压力会很大,因此可以通过MaxMultipartMemory属性来设置缓冲区大小:

ini 复制代码
 //8M
 engine.MaxMultipartMemory = 8 << 20

上传文件时,不限制文件大小可以会导致服务存储空间暴涨,因为有必须限制上传文件大小:

go 复制代码
 fileMaxSize := 4 << 20 //4M
 if int(file.Size) > fileMaxSize {
   c.String(http.StatusBadRequest, "文件不允许大小于4M")
   return
 }

对文件类型,也可以进行限制:

go 复制代码
 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值。

关于文件大小、类型等限制,下面是一个完整的示例:

go 复制代码
 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命令上传文件:

ruby 复制代码
 $ curl -F "file=@./1.jpg" -X POST "http://localhost:8080/upload"
 '1.jpg' 上传成功!

多个文件上传

如果要上传多个文件,多次调用gin.ContextFormFile()方法也是可以的,但更好的方式是使用gin.ContextMultipartForm()方法:

go 复制代码
 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命令上传多个文件:

ini 复制代码
$ curl -F "upload=@./1.jpg" -F "upload=@./2.jpg" -X POST "http://localhost:8080/uploadMul
2 files uploaded

多文件上传有关于文件类型、大小限制等设置,都与单个文件上传类型一样,可以参与单文件上传的完整案例。

小结

Go标准库net/http对文件上传已经提供了非常完善的支持,而Gin框架在其基础上进一步封装,因此使用Gin开发文件上传功能时,只需要简单几行代码便可以实现。

相关推荐
zopple9 分钟前
常见的 Spring 项目目录结构
java·后端·spring
cjy0001112 小时前
springboot的 nacos 配置获取不到导致启动失败及日志不输出问题
java·spring boot·后端
小江的记录本3 小时前
【事务】Spring Framework核心——事务管理:ACID特性、隔离级别、传播行为、@Transactional底层原理、失效场景
java·数据库·分布式·后端·sql·spring·面试
sheji34163 小时前
【开题答辩全过程】以 基于springboot的校园失物招领系统为例,包含答辩的问题和答案
java·spring boot·后端
程序员cxuan3 小时前
人麻了,谁把我 ssh 干没了
人工智能·后端·程序员
wuyikeer4 小时前
Spring Framework 中文官方文档
java·后端·spring
Victor3565 小时前
MongoDB(61)如何避免大文档带来的性能问题?
后端
Victor3565 小时前
MongoDB(62)如何避免锁定问题?
后端
wuyikeer5 小时前
Spring BOOT 启动参数
java·spring boot·后端
子木HAPPY阳VIP6 小时前
Ubuntu 22.04 VMware 设置固定IP配置
人工智能·后端·目标检测·机器学习·目标跟踪