Gin -- 文件上传

0. 文件上传格式

1. form表单上传

<form enctype="multipart/form-data">    <!- 必须设置enctype ->
    
ctx.FormFile()获取文件对象

1. 单个文件上传

  1. multipart/form-data格式用于文件上传,FormFile()获取
  2. gin文件上传与原生的net/http方法类似,不同在于gin把原生的request封装到c.Request中

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <form action="http://localhost:8080/upload" method="post" enctype="multipart/form-data">
          上传文件:<input type="file" name="file" >
          <input type="submit" value="提交">
    </form>
</body>
</html>

main.go

package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	r := gin.Default()
	// 限制上传文件的最大字节数8MB,默认为32MB
	r.MaxMultipartMemory = 8 << 20
	r.POST("/upload", func(context *gin.Context) {
		file, err := context.FormFile("file")
		if err != nil || file == nil {
			context.String(500, "上传图片出错")
		}
		// 将文件保存在根目录下的images/文件名,前提是根目录下有images这个文件夹
		context.SaveUploadedFile(file, "./images"+file.Filename)
		context.String(http.StatusOK, "文件保存成功")
	})
	r.Run(":8002")
}

2. 特定文件上传

有的用户上传文件需要限制上传文件的类型以及上传文件的大小,但是gin框架暂时没有这些函数(也有可能是我没找到),因此基于原生的函数写法自己写了一个可以限制大小以及文件类型的上传函数

1. http原生获取文件对象

package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/gin-gonic/gin"
)

func main() {
    r := gin.Default()
    r.POST("/upload", func(c *gin.Context) {
        // 另一种获取文件的方式,用http原生方法获取
        _, headers, err := c.Request.FormFile("file")
        if err != nil {
            log.Printf("Error when try to get file: %v", err)
        }
        //headers.Size 获取文件大小
        if headers.Size > 1024*1024*2 {
            fmt.Println("文件太大了")
            return
        }
        //headers.Header.Get("Content-Type")获取上传文件的类型
        if headers.Header.Get("Content-Type") != "image/png" {
            fmt.Println("只允许上传png图片")
            return
        }
        c.SaveUploadedFile(headers, "./video/"+headers.Filename)
        c.String(http.StatusOK, headers.Filename)
    })
    r.Run()
}

2. gin获取文件对象

package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	r := gin.Default()
	// 限制上传文件的最大字节数8MB,默认为32MB
	r.MaxMultipartMemory = 8 << 20
	r.POST("/upload", func(context *gin.Context) {
		file, err := context.FormFile("file")
		if err != nil || file == nil {
			context.String(500, "上传图片出错")
		}
		if file.Size > 1024 * 1024 * 2{
			context.String(http.StatusBadRequest, "文件太大了")
		}
		if file.Header.Get("Content-Type") != "image/png" {
			context.String(http.StatusBadRequest, "只允许上传图片")
		}
		// 将文件保存在根目录下的images/文件名,前提是根目录下有images这个文件夹
		context.SaveUploadedFile(file, "./images"+file.Filename)
		context.String(http.StatusOK, "文件保存成功")
	})
	r.Run(":8002")
}

3. 多个文件上传

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <form action="http://localhost:8000/upload" method="post" enctype="multipart/form-data">
          上传文件:<input type="file" name="files" multiple>
          <input type="submit" value="提交">
    </form>
</body>
</html>

main.go

package main

import (
   "github.com/gin-gonic/gin"
   "net/http"
   "fmt"
)

// gin的helloWorld

func main() {
   // 1.创建路由,默认使用了2个中间件Logger(), Recovery()
   r := gin.Default()

   // 限制表单上传大小 8MB,默认为32MB
   r.MaxMultipartMemory = 8 << 20

   r.POST("/upload", func(c *gin.Context) {
      
      form, err := c.MultipartForm()
      if err != nil {
         c.String(http.StatusBadRequest, fmt.Sprintf("get err %s", err.Error()))
      }
      // 获取所有图片
      files := form.File["files"]
      // 遍历所有图片
      for _, file := range files {
         // 逐个存
         if err := c.SaveUploadedFile(file, file.Filename); err != nil {
            c.String(http.StatusBadRequest, fmt.Sprintf("upload err %s", err.Error()))
            return
         }
      }
      c.String(200, fmt.Sprintf("upload ok %d files", len(files)))
   })
   //默认端口号是8080
   r.Run(":8000")
}

4. 常用方法

1. 限制上传文件大小

// 为 multipart forms 设置较低的内存限制 (默认是 32 MiB)
	router.MaxMultipartMemory = 8 << 20  // 8 MiB

2. 保存文件

// 定义文件保存路径
uploadPath := "./images" + file.Filename
// 将文件保存在根目录下的images/文件名,前提是根目录下有images这个文件夹
ctx.SaveUploadedFile(file,uploadPath)

5. 参考示例

1. 单个文件上传

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <form action="http://localhost:8080/upload" method="post" enctype="multipart/form-data">
          上传文件:<input type="file" name="file" >
          <input type="submit" value="提交">
    </form>
</body>
</html>

main.go

package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	r := gin.Default()
	// 限制上传文件的最大字节数8MB,默认为32MB
	r.MaxMultipartMemory = 8 << 20
	r.POST("/upload", func(ctx *gin.Context) {
		file, err := ctx.FormFile("file")
		if err != nil || file == nil {
			ctx.String(500, "上传图片出错")
		}
		// 将文件保存在根目录下的images/文件名,前提是根目录下有images这个文件夹
		ctx.SaveUploadedFile(file, "./images"+file.Filename)
		ctx.String(http.StatusOK, "文件保存成功")
	})
	r.Run(":8002")
}

2. 多文件上传

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <form action="http://localhost:8000/upload" method="post" enctype="multipart/form-data">
          上传文件:<input type="file" name="files" multiple>
          <input type="submit" value="提交">
    </form>
</body>
</html>

main.go

package main

import (
   "github.com/gin-gonic/gin"
   "net/http"
   "fmt"
)

// gin的helloWorld

func main() {
   // 1.创建路由,默认使用了2个中间件Logger(), Recovery()
   r := gin.Default()

   // 限制表单上传大小 8MB,默认为32MB
   r.MaxMultipartMemory = 8 << 20

   r.POST("/upload", func(c *gin.Context) {
      
      form, err := c.MultipartForm()
      if err != nil {
         c.String(http.StatusBadRequest, fmt.Sprintf("get err %s", err.Error()))
      }
      // 获取所有图片
      files := form.File["files"]
      // files := form.File["upload[]"]  ,此时input的name值必须为name="upload[]"
      // 遍历所有图片
      for _, file := range files {
         // 逐个存
         if err := c.SaveUploadedFile(file, file.Filename); err != nil {
            c.String(http.StatusBadRequest, fmt.Sprintf("upload err %s", err.Error()))
            return
         }
      }
      c.String(200, fmt.Sprintf("upload ok %d files", len(files)))
   })
   //默认端口号是8080
   r.Run(":8000")
}

3. 自定义文件上传(大小,文件类型)

有的用户上传文件需要限制上传文件的类型以及上传文件的大小,但是gin框架暂时没有这些函数(也有可能是我没找到),因此基于原生的函数写法自己写了一个可以限制大小以及文件类型的上传函数

4. http原生获取文件对象

package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/gin-gonic/gin"
)

func main() {
    r := gin.Default()
    r.POST("/upload", func(c *gin.Context) {
        // 另一种获取文件的方式,用http原生方法获取
        _, headers, err := c.Request.FormFile("file")
        if err != nil {
            log.Printf("Error when try to get file: %v", err)
        }
        //headers.Size 获取文件大小
        if headers.Size > 1024*1024*2 {
            fmt.Println("文件太大了")
            return
        }
        //headers.Header.Get("Content-Type")获取上传文件的类型
        if headers.Header.Get("Content-Type") != "image/png" {
            fmt.Println("只允许上传png图片")
            return
        }
        c.SaveUploadedFile(headers, "./video/"+headers.Filename)
        c.String(http.StatusOK, headers.Filename)
    })
    r.Run()
}
posted @ 2024-01-17 17:03  河图s  阅读(151)  评论(0)    收藏  举报