七叶笔记 » golang编程 » Golang GinWeb框架2-文件上传/恐慌处理

Golang GinWeb框架2-文件上传/恐慌处理

简介


本文接着上文(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   -H "Content-Type: multipart/form-data" -F "file=@文件名"  

  • 多文件上传, 详情参考(
 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  -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   

参考文档


Gin官方仓库:


END已结束

欢迎大家留言, 订阅, 交流哦!


往期回顾


Golang GinWeb框架-快速入门/参数解析

Golang与亚马逊对象存储服务AmazonS3快速入门

Golang+Vue实现Websocket全双工通信入门

GolangWeb编程之控制器方法HandlerFunc与中间件Middleware

Golang连接MySQL执行查询并解析-告别结构体

Golang的一种发布订阅模式实现

Golang 并发数据冲突检测器(Data Race Detector)与并发安全

Golang”驱动”MongoDB-快速入门(“快码加鞭”)

相关文章