当前位置:   article > 正文

探索Gin框架:Golang使用Gin完成文件上传_golang gin multipartform

golang gin multipartform

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站https://www.captainbed.cn/kitie

前言

在之前的文章中,我们讲解了Gin框架的快速入门使用,今天我们来聊聊如何使用Gin实现文件上传。

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

目录

​编辑

前言

使用原生net/http库实现文件上传

使用Gin实现文件上传

单个文件上传

FormFile()获取文件

SaveUploadedFile()保存到本地 

设置缓冲区大小

限制文件大小

限制文件类型

完整示例

测试文件上传

多个文件上传

MultipartForm()获取多个文件

测试文件上传

总结


使用原生net/http库实现文件上传

我们首先看看实现一个HTTP服务器,提供文件上传功能的简单示例

  1. package main
  2. import (
  3. "io"
  4. "io/ioutil"
  5. "log"
  6. "net/http"
  7. "github.com/julienschmidt/httprouter"
  8. )
  9. const (
  10. MAX_UPLOAD_SIZE = 1024 * 1024 * 20 //最大上传大小,50MB
  11. )
  12. func main() {
  13. r := RegisterHandlers()
  14. http.ListenAndServe(":8080", r) // 开启一个http服务
  15. }
  16. // 定义路由
  17. func RegisterHandlers() *httprouter.Router {
  18. router := httprouter.New()
  19. router.POST("/upload", uploadHandler)
  20. return router
  21. }
  22. // 文件上传接口
  23. func uploadHandler(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
  24. r.Body = http.MaxBytesReader(w, r.Body, MAX_UPLOAD_SIZE)
  25. if err := r.ParseMultipartForm(MAX_UPLOAD_SIZE); err != nil {
  26. log.Printf("File is too big")
  27. return
  28. }
  29. file, headers, err := r.FormFile("file")
  30. if err != nil {
  31. log.Printf("Error when try to get file: %v", err)
  32. return
  33. }
  34. //获取上传文件的类型
  35. if headers.Header.Get("Content-Type") != "image/png" {
  36. log.Printf("只允许上传png图片")
  37. return
  38. }
  39. data, err := ioutil.ReadAll(file)
  40. if err != nil {
  41. log.Printf("Read file error: %v", err)
  42. return
  43. }
  44. fn := headers.Filename
  45. err = ioutil.WriteFile("./video/"+fn, data, 0666)
  46. if err != nil {
  47. log.Printf("Write file error: %v", err)
  48. return
  49. }
  50. w.WriteHeader(http.StatusCreated)
  51. io.WriteString(w, "Uploaded successfully")
  52. }

如上我们通过r.FormFile函数获取上传的文件对象,以及文件的相关信息。然后通过headers.Header.Get函数获取上传文件的类型,判断类型是否符合要求。接着,使用ioutil.ReadAll函数读取文件的内容,并将其存储在data变量中。然后,通过headers.Filename获取上传文件的文件名,并使用ioutil.WriteFile函数将文件内容写入到指定路径下的文件中。

使用Gin实现文件上传

单个文件上传

FormFile()获取文件

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

  1. engine := gin.Default()
  2. engine.POST("/upload", func(c *gin.Context) {
  3. file, err := c.FormFile("file")
  4. })
  5. engine.Run()

SaveUploadedFile()保存到本地 

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

  1.  dst := "./uploads/" + file.Filename
  2.  c.SaveUploadedFile(file,"./uploadFile")

设置缓冲区大小

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

  1.  //8M
  2.  engine.MaxMultipartMemory = 8 << 20

限制文件大小

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

  1.  fileMaxSize := 4 << 20 //4M
  2.  if int(file.Size) > fileMaxSize {
  3.    c.String(http.StatusBadRequest, "文件不允许大小于4M")
  4.    return
  5.  }

限制文件类型

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

  1.  reader, err := file.Open()
  2.  if err != nil {
  3.    fmt.Println(err)
  4.    return
  5.  }
  6.  b := make([]byte, 512)
  7.  reader.Read(b)
  8.  ​
  9.  contentType := http.DetectContentType(b)
  10.  if contentType != "image/jpeg" && contentType != "image/png" {
  11.    c.String(http.StatusOK, "文件格式错误")
  12.    return
  13.  }

在上面的代码中,我们读取文件的前512个字节,再调用http.DetectContentType()便可以获取文件的MIME值。

完整示例

  1.  package main
  2.  ​
  3.  import (
  4.   "fmt"
  5.   "log"
  6.   "net/http"
  7.  ​
  8.   "github.com/gin-gonic/gin"
  9.  )
  10.  ​
  11.  func main() {
  12.   engine := gin.Default()
  13.   //8M
  14.   engine.MaxMultipartMemory = 8 << 20
  15.   engine.POST("/upload", func(c *gin.Context) {
  16.   file, err := c.FormFile("file")
  17.   if err != nil {
  18.   log.Println(err)
  19.   c.String(http.StatusBadRequest, "文件上传失败")
  20.   return
  21.   }
  22.   fileMaxSize := 4 << 20 //4M
  23.   if int(file.Size) > fileMaxSize {
  24.   c.String(http.StatusBadRequest, "文件不允许大小于32KB")
  25.   return
  26.   }
  27.  ​
  28.   reader, err := file.Open()
  29.   if err != nil {
  30.   fmt.Println(err)
  31.   return
  32.   }
  33.   b := make([]byte, 512)
  34.   reader.Read(b)
  35.  ​
  36.   contentType := http.DetectContentType(b)
  37.   if contentType != "image/jpeg" && contentType != "image/png" {
  38.   c.String(http.StatusOK, "文件格式错误")
  39.   return
  40.   }
  41.  ​
  42.   dst := "./uploads/" + file.Filename
  43.   c.SaveUploadedFile(file, dst)
  44.   c.String(http.StatusOK, fmt.Sprintf("'%s' 上传成功!", file.Filename))
  45.   })
  46.   engine.Run()
  47.  }
  48.  ​

测试文件上传

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

多个文件上传

MultipartForm()获取多个文件

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

  1.  package main
  2.  ​
  3.  import (
  4.   "fmt"
  5.   "log"
  6.   "net/http"
  7.  ​
  8.   "github.com/gin-gonic/gin"
  9.  )
  10.  ​
  11.  func main() {
  12.   engine := gin.Default()
  13.   engine.POST("/uploadMul", func(c *gin.Context) {
  14.   form, err := c.MultipartForm()
  15.   if err != nil {
  16.   log.Println(err)
  17.   c.String(http.StatusBadRequest, "文件上传失败")
  18.   return
  19.   }
  20.   files := form.File["upload"]
  21.   for _, file := range files {
  22.   fmt.Println(file.Filename)
  23.   }
  24.   c.String(http.StatusOK, fmt.Sprintf("%d files uploaded!", len(files)))
  25.   })
  26.   engine.Run()
  27.  }

测试文件上传

运行程序后,使用curl命令上传多个文件:

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

总结

Go标准库net/http对文件上传已经提供了非常完善的支持,可以满足我们大部分需求,Gin框架在其基础做了封装,让我们使用起来更加方便迅速。

感谢阅读~

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/147154
推荐阅读
  

闽ICP备14008679号