Golang使用Gin实现文件上传的示例代码

 更新时间:2024年02月03日 09:23:03   作者:鼠鼠我捏,要死了捏  
本文我们主要介绍了Golang如何使用Gin实现文件上传,Go标准库net/http对文件上传已经提供了非常完善的支持,而Gin框架在其基础上进一步封装,因此使用Gin开发文件上传功能时,只需要简单几行代码便可以实现,需要的朋友可以参考下

前言

今天我们来聊聊如何使用Gin实现文件上传。

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

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

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

package main
 
import (
    "io"
    "io/ioutil"
    "log"
    "net/http"
 
    "github.com/julienschmidt/httprouter"
)
 
const (
    MAX_UPLOAD_SIZE = 1024 * 1024 * 20 //最大上传大小,50MB
)
 
func main() {
    r := RegisterHandlers()
 
    http.ListenAndServe(":8080", r)  // 开启一个http服务
}
 
// 定义路由
func RegisterHandlers() *httprouter.Router {
    router := httprouter.New()
 
    router.POST("/upload", uploadHandler)
 
    return router
}
// 文件上传接口
func uploadHandler(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
    r.Body = http.MaxBytesReader(w, r.Body, MAX_UPLOAD_SIZE)
    if err := r.ParseMultipartForm(MAX_UPLOAD_SIZE); err != nil {
        log.Printf("File is too big")
        return
    }
    file, headers, err := r.FormFile("file")
    if err != nil {
        log.Printf("Error when try to get file: %v", err)
        return
    }
    //获取上传文件的类型
    if headers.Header.Get("Content-Type") != "image/png" {
        log.Printf("只允许上传png图片")
        return
    }
    data, err := ioutil.ReadAll(file)
    if err != nil {
        log.Printf("Read file error: %v", err)
        return
    }
    fn := headers.Filename
    err = ioutil.WriteFile("./video/"+fn, data, 0666)
    if err != nil {
        log.Printf("Write file error: %v", err)
        return
    }
    w.WriteHeader(http.StatusCreated)
    io.WriteString(w, "Uploaded successfully")
}

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

使用Gin实现文件上传

单个文件上传

FormFile()获取文件

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

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

SaveUploadedFile()保存到本地 

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

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

设置缓冲区大小

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

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

限制文件大小

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

 fileMaxSize := 4 << 20 //4M
 if int(file.Size) > fileMaxSize {
   c.String(http.StatusBadRequest, "文件不允许大小于4M")
   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
 }

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

完整示例

 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 -F "file=@./1.jpg" -X POST "http://localhost:8080/upload"
 '1.jpg' 上传成功!

多个文件上传

MultipartForm()获取多个文件

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

 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命令上传多个文件:

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

总结

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

以上就是Golang使用Gin实现文件上传的示例代码的详细内容,更多关于Golang Gin文件上传的资料请关注脚本之家其它相关文章!

相关文章

  • Go基础语法的使用

    Go基础语法的使用

    本文主要介绍了Go基础语法的使用,包括标识符、关键字、行分隔符、var关键字、:=运算符、空格、注释、package、import、输入输出、运算符、条件控制、循环等,感兴趣的可以了解一下
    2023-11-11
  • 详解Go flag实现二级子命令的方法

    详解Go flag实现二级子命令的方法

    这篇文章主要介绍了Go flag 详解,实现二级子命令,本文就探讨一下 Go 语言中如何写一个拥有类似特性的命令行程序,需要的朋友可以参考下
    2022-07-07
  • 使用go语言实现cors中间件

    使用go语言实现cors中间件

    CORS是一种浏览器安全机制,用于控制在Web应用程序中不同源(Origin)之间的资源共享,本文将给大家介绍如何使用go语言实现cors中间件,文中有详细的代码示例供大家参考,需要的朋友可以参考下
    2023-09-09
  • Golang实现AES对称加密的过程详解

    Golang实现AES对称加密的过程详解

    AES是一个对称密码,旨在取代DES成为广泛使用的标准,本文给大家分享Golang实现AES对称加密的过程,本文附有Golang实现AES加密ECB模式的源码,感兴趣的朋友跟随小编一起学习下吧
    2021-05-05
  • go语言实现两个协程交替打印

    go语言实现两个协程交替打印

    这篇文章主要介绍了go语言实现两个协程交替打印,文章主要分享了两种方法使用两个channel和使用一个channel,内容介绍详细具有一定的参考价值,需要的小伙伴可以参考一下
    2022-03-03
  • Golang二维数组的使用方式

    Golang二维数组的使用方式

    之前给大家讲过很多二维数组的知识,今天重点给大家介绍Golang二维数组的使用方式,通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2021-05-05
  • Golang 中实现 Set的思路详解

    Golang 中实现 Set的思路详解

    本文介绍了Go中两种set的实现原理,并在此基础介绍了对应于它们的两个包简单使用,本文介绍的非常详细,需要的朋友参考下吧
    2024-01-01
  • golang API开发过程的中的自动重启方式(基于gin框架)

    golang API开发过程的中的自动重启方式(基于gin框架)

    这篇文章主要介绍了golang API开发过程的中的自动重启方式(基于gin框架),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-12-12
  • go map搬迁的实现

    go map搬迁的实现

    本文主要介绍了go map搬迁的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • golang限流库两个大bug(半年之久无人提起)

    golang限流库两个大bug(半年之久无人提起)

    最近我的同事在使用uber-go/ratelimit[1]这个限流库的时候,遇到了两个大 bug,这两个 bug 都是在这个库的最新版本(v0.3.0)中存在的,而这个版本从 7 月初发布都已经过半年了,都没人提 bug,难道大家都没遇到过么
    2023-12-12

最新评论