[GoLang]Gin实现文件上传

提示:简单实现两个小功能,如有需要可以自行扩展


前言

如何使用Gin框架实现文件上传功能?这里我们使用地鼠文档的内容作为示例

这里我们将文件上传分为两类:

  • 一类是单文件上传,实现此功能使用的是Context包下的FormFile()方法
  • 另一类是多文件上传,实现此功能使用Context包下的MultipartForm()方法

一、单文件上传

单文件上传是指前端请求时给后端一次性发送一个文件,通过Gin框架的处理,我们可以将前端传给的文件保存到我们的工程目录中,其保存路径是可以自定义的

1.前端实现

这里我们使用示例代码,前端界面是一个最简易的上传。
这里不需要创建vue项目再单独启动了,创建一个html文件,使用浏览器打开本地文件即可
已经在表单中填写了提交方式为Post以及请求的路径为http://localhost:8080/upload

<!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>

2.后端实现

后端的代码其实非常简单,我们来梳理一下逻辑

  1. 首先得创建Gin框架的基本路由,然后调用其POST方法进行传输文件
  2. Context包下的FormFile()方法需要传什么参数?返回什么东西?这里我们可以看到,需要传递一个string类型的name参数,这里的name需要和前端<input>标签中定义的name保持一致。返回一个FileHeader类型的结构体以及一个error在这里插入图片描述在这里插入图片描述
  3. 我们看到返回的FileHeader中定义了什么?文件的名字,大小,协议头部信息等。我们这个案例中在页面显示下文件名
  4. 如果传输成功在界面上显示文件名称,如果传输失败返回错误信息,逻辑梳理结束

代码实现:

func main() {
	r := gin.Default()
	r.MaxMultipartMemory = 8 << 20 // 可以限制文件上传大小
	r.POST("/upload", func(c *gin.Context) {
		file, err := c.FormFile("file")// 这里的file需要和前端<input>标签中的file对应
		if err != nil {
			c.String(500, "上传文件出错")
		}
		c.SaveUploadedFile(file, "./gin/gin-singleFile/static/"+file.Filename)
		c.String(http.StatusOK, file.Filename)
	})
	r.Run(":8080")
}

注意:

SaveUploadedFile()方法中需要传递得到的file文件以及定义保存路径

  • 如果我们只填写c.SaveUploadedFile(file, file.Filename),这个时候文件就会保存在工程文件根目录下,也就是和go.mod文件同级中,并且文件名就是file.Filename。这样其实默认是保存在./
  • 如果我们需要保存在其他目录下,就可以根据实际情况调整,./xxx/xxx/xxx
  • 可以自己输入不同的文件目录,测试一下效果

效果测试:

浏览器上传文件
在这里插入图片描述

这时候选择文件上传即可,注意不要忘记运行后端
在这里插入图片描述
后端将文件保存在指定路径中
在这里插入图片描述
这时候就完成了单文件上传的功能

二、多文件上传

多文件上传也是相同的逻辑,只不过Gin框架处理的时候需要使用MultipartForm()方法,前端上传多个文件让Gin框架处理,我们拿到的是一个文件map

在这里插入图片描述

该方法不需要传递任何参数,并且返回的是个Form结构体,这个Form中又有什么东西呢?原来是将File封装到了map中并且类型是FileHeader,那么这个FileHeader在上边我们已经介绍过了,定义的是文件相关的字段,这样将其封装到map中,可以传递多个file
在这里插入图片描述

1.前端实现

代码如下(示例):

<!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="files" multiple>
          <input type="submit" value="提交">
    </form>
</body>
</html>

2.后端实现

代码实现

func main() {
	r := gin.Default()
	r.POST("/upload", func(c *gin.Context) {
		form, err := c.MultipartForm()
		if err != nil {
			c.String(http.StatusBadRequest, fmt.Sprintf("err is %v", err.Error()))
		}

		files := form.File["files"]
		for _, file := range files {
			if err2 := c.SaveUploadedFile(file, "./gin/gin-multiFile/static/"+file.Filename); err2 != nil {
				c.String(http.StatusBadRequest, fmt.Sprintf("upload err  %v", err2.Error()))
				return
			}
		}
		c.String(200, fmt.Sprintf("upload is ok %d files", len(files)))
	})
	r.Run(":8080")
}

我们使用for range来遍历这个文件map,将文件一一取出并保存在指定文件目录下

注意:

  • form.File(“files”)中的"files"需要和前端<input>标签中保持一致,这是前后端进行交互的一个重要名称
  • 在上传完成后,对获得的文件map进行计算长度,这里使用的是len()进行长度计算,得到的是files中的文件个数

效果测试:

浏览器上传两个文件
在这里插入图片描述
提交后显示文件个数
在这里插入图片描述
后端文件保存在指定路径
在这里插入图片描述
此时多文件上传功能也已经实现

总结

Gin框架处理单文件和多文件上传有各自的方法,单文件上传使用的是Context包下的FormFile(),多文件上传使用的是Context包下的MultipartForm(),可以自行测试效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值