简介

本文接着上文(Golang GinWeb框架-快速入门/参数解析)继续探索GinWeb框架

上传文件

单文件上传

注意: 文件名必须是安全可信赖的, 需要去掉路径信息,保留文件名即可

package main 
 
import ( 
  "fmt" 
  "github.com/gin-gonic/gin" 
  "log" 
  "net/http" 
  "os" 
) 
 
func main() { 
  router := gin.Default() 
  // Set a lower memory limit for multipart forms (default is 32 MiB) 
  // 设置请求表单最大内存限制,默认是30MB 
 
  //内部调用http请求的ParseMultipartForm方法,该方法要求传入一个字节数, 要取MultipartForm字段的数据,先使用ParseMultipartForm()方法解析Form,解析时会读取所有数据,但需要指定保存在内存中的最大字节数,剩余的字节数会保存在临时磁盘文件中 
  maxMultipartMemory := int64(8 << 20) 
  log.Printf("解析文件到内存的最大字节:%d", maxMultipartMemory) 
  router.MaxMultipartMemory = maxMultipartMemory  // 8 MiB 
  router.POST("/upload", func(c *gin.Context) { 
    // single file 
    file, _ := c.FormFile("file")  //FormFile从表单中返回第一个匹配到的文件对象(结构) 
    log.Printf("获取到的文件名:%s", file.Filename)  //文件名必须是安全可信耐的,需要去掉路径信息,保留文件名即可 
 
    // Upload the file to specific dst. 
    currentPath, _ := os.Getwd()  //获取当前文件路径 
    dst := currentPath + "/" + file.Filename 
    log.Printf("保存文件绝对路径:%s", dst) 
    c.SaveUploadedFile(file, dst) 
 
    c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename)) 
  }) 
  router.Run(":8080") 
} 
 
//模拟单文件上传: 
//curl -X POST http://localhost:8080/upload  -H "Content-Type: multipart/form-data" -F "file=@文件名"

多文件上传, 详情参考(https://github.com/gin-gonic/examples/blob/master/upload-file/multiple/main.go)

package main 
 
import ( 
  "fmt" 
  "github.com/gin-gonic/gin" 
  "log" 
  "net/http" 
  "os" 
) 
 
func main() { 
  router := gin.Default() 
  // Set a lower memory limit for multipart forms (default is 32 MiB) 
  // 设置请求表单最大内存限制,默认是30MB 
  //内部调用http请求的ParseMultipartForm方法,该方法要求传入一个字节数, 要取MultipartForm字段的数据,先使用ParseMultipartForm()方法解析Form,解析时会读取所有数据,但需要指定保存在内存中的最大字节数,剩余的字节数会保存在临时磁盘文件中 
  maxMultipartMemory := int64(8 << 20) 
  log.Printf("解析文件到内存的最大字节:%d", maxMultipartMemory) 
  router.MaxMultipartMemory = maxMultipartMemory  // 8 MiB 
  router.POST("/upload", func(c *gin.Context) { 
    // Upload the file to specific dst. 
    currentPath, _ := os.Getwd()  //获取当前文件路径 
    // Multipart form 
    form, _ := c.MultipartForm() //多文件表单 
    files := form.File["upload[]"] //通过前端提供的键名获取文件数组 
    for _, file := range files { 
      dst := currentPath + "/" + file.Filename 
      log.Printf("保存文件绝对路径:%s", dst) 
      // Upload the file to specific dst. 
      c.SaveUploadedFile(file, dst) 
    } 
    c.String(http.StatusOK, fmt.Sprintf("%d files uploaded!", len(files))) 
  }) 
  router.Run(":8080") 
} 
 
//模拟多文件上传 
//curl -X POST http://localhost:8080/upload -H "Content-Type: multipart/form-data" -F "upload[]=@文件1" -F "upload[]=@文件2"

路由分组

路由分组可用于新老接口兼容, 针对不同分组的路由使用不同的中间件处理逻辑等

func main() { 
  router := gin.Default() 
  // Simple group: v1  路由分组1 
  v1 := router.Group("/v1") 
  { 
    v1.POST("/login", loginEndpoint) 
    v1.POST("/submit", submitEndpoint) 
    v1.POST("/read", readEndpoint) 
  } 
  // Simple group: v2  路由分组2 
  v2 := router.Group("/v2") 
  { 
    v2.POST("/login", loginEndpoint) 
    v2.POST("/submit", submitEndpoint) 
    v2.POST("/read", readEndpoint) 
  } 
  router.Run(":8080") 
}

中间件

我们可以用下面的两种方式初始化Gin引擎

r := gin.New() //得到一个不使用任何中间件的Gin引擎Engine对象r 
 
// Default With the Logger and Recovery middleware already attached 
// 默认方法使用Logger(日志记录器)和Recovery(异常自恢复)中间件 
r := gin.Default()

自定义程序崩溃后的处理方式(邮件,微信,短信等告警)

package main 
 
import ( 
  "fmt" 
  "github.com/gin-gonic/gin" 
  "log" 
  "net/http" 
) 
 
func CustomRecovery() gin.HandlerFunc { 
  return func(c *gin.Context) { 
    defer func() { 
      //if r := recover(); r != nil { 
      //  log.Printf("崩溃信息:%s", r) 
      //} 
 
      if err, ok := recover().(string); ok { 
        log.Printf("您可以在这里完成告警任务,邮件,微信等告警") 
        c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err)) 
      } 
      c.AbortWithStatus(http.StatusInternalServerError) 
    }() 
    c.Next() 
  } 
} 
 
func main() { 
  // Creates a router without any middleware by default 
  r := gin.New() 
 
  // Global middleware 
  // Logger middleware will write the logs to gin.DefaultWriter even if you set with GIN_MODE=release. 
  // By default gin.DefaultWriter = os.Stdout 
  r.Use(gin.Logger()) 
 
  // Recovery middleware recovers from any panics and writes a 500 if there was one. 
  //r.Use(CustomRecovery())  //使用自定义中间件处理程序崩溃 
 
  //使用匿名函数组成中间件,处理程序崩溃 
  r.Use(func( c *gin.Context){ 
    defer func() { 
      if err, ok := recover().(string); ok { 
        log.Printf("您可以在这里完成告警任务,邮件,微信等告警") 
        c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err)) 
      } 
      c.AbortWithStatus(http.StatusInternalServerError) 
    }() 
    c.Next() 
  }) 
 
  r.GET("/panic", func(c *gin.Context) { 
    // panic with a string -- the custom middleware could save this to a database or report it to the user 
    panic("程序崩溃") 
  }) 
 
  r.GET("/", func(c *gin.Context) { 
    c.String(http.StatusOK, "ohai") 
  }) 
 
  // Listen and serve on 0.0.0.0:8080 
  r.Run(":8080") 
} 
//模拟程序崩溃: curl http://localhost:8080/panic

参考文档

Gin官方仓库:https://github.com/gin-gonic/gin