Golang GinWeb框架2-文件上傳/程序panic崩潰后自定義處理方式
簡(jiǎn)介
本文接著上文(Golang GinWeb框架-快速入門/參數(shù)解析)繼續(xù)探索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)
- // 設(shè)置請(qǐng)求表單最大內(nèi)存限制,默認(rèn)是30MB
- //內(nèi)部調(diào)用http請(qǐng)求的ParseMultipartForm方法,該方法要求傳入一個(gè)字節(jié)數(shù), 要取MultipartForm字段的數(shù)據(jù),先使用ParseMultipartForm()方法解析Form,解析時(shí)會(huì)讀取所有數(shù)據(jù),但需要指定保存在內(nèi)存中的最大字節(jié)數(shù),剩余的字節(jié)數(shù)會(huì)保存在臨時(shí)磁盤文件中
- maxMultipartMemory := int64(8 << 20)
- log.Printf("解析文件到內(nèi)存的最大字節(jié):%d", maxMultipartMemory)
- router.MaxMultipartMemory = maxMultipartMemory // 8 MiB
- router.POST("/upload", func(c *gin.Context) {
- // single file
- file, _ := c.FormFile("file") //FormFile從表單中返回第一個(gè)匹配到的文件對(duì)象(結(jié)構(gòu))
- log.Printf("獲取到的文件名:%s", file.Filename) //文件名必須是安全可信耐的,需要去掉路徑信息,保留文件名即可
- // Upload the file to specific dst.
- currentPath, _ := os.Getwd() //獲取當(dāng)前文件路徑
- dst := currentPath + "/" + file.Filename
- log.Printf("保存文件絕對(duì)路徑:%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)
- // 設(shè)置請(qǐng)求表單最大內(nèi)存限制,默認(rèn)是30MB
- //內(nèi)部調(diào)用http請(qǐng)求的ParseMultipartForm方法,該方法要求傳入一個(gè)字節(jié)數(shù), 要取MultipartForm字段的數(shù)據(jù),先使用ParseMultipartForm()方法解析Form,解析時(shí)會(huì)讀取所有數(shù)據(jù),但需要指定保存在內(nèi)存中的最大字節(jié)數(shù),剩余的字節(jié)數(shù)會(huì)保存在臨時(shí)磁盤文件中
- maxMultipartMemory := int64(8 << 20)
- log.Printf("解析文件到內(nèi)存的最大字節(jié):%d", maxMultipartMemory)
- router.MaxMultipartMemory = maxMultipartMemory // 8 MiB
- router.POST("/upload", func(c *gin.Context) {
- // Upload the file to specific dst.
- currentPath, _ := os.Getwd() //獲取當(dāng)前文件路徑
- // Multipart form
- form, _ := c.MultipartForm() //多文件表單
- files := form.File["upload[]"] //通過前端提供的鍵名獲取文件數(shù)組
- for _, file := range files {
- dst := currentPath + "/" + file.Filename
- log.Printf("保存文件絕對(duì)路徑:%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"
路由分組
路由分組可用于新老接口兼容, 針對(duì)不同分組的路由使用不同的中間件處理邏輯等
- 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() //得到一個(gè)不使用任何中間件的Gin引擎Engine對(duì)象r
- // Default With the Logger and Recovery middleware already attached
- // 默認(rèn)方法使用Logger(日志記錄器)和Recovery(異常自恢復(fù))中間件
- 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("您可以在這里完成告警任務(wù),郵件,微信等告警")
- 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()) //使用自定義中間件處理程序崩潰
- //使用匿名函數(shù)組成中間件,處理程序崩潰
- r.Use(func( c *gin.Context){
- defer func() {
- if err, ok := recover().(string); ok {
- log.Printf("您可以在這里完成告警任務(wù),郵件,微信等告警")
- 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官方倉(cāng)庫(kù):https://github.com/gin-gonic/gin