当前位置:网站首页>GIN文件上传与返回

GIN文件上传与返回

2022-08-09 12:44:00 一叶知秋@qqy

前言

感谢开源项目gin-vue-admin,以及1010工作室的教程,项目文档
我只是在跟着学习,然后记录下笔记而已,可能会有新的代码加入,但是本质还是跟着学习的一个过程。

上传文件

使用postman模拟上传文件
无论使用postman还是前端的同学直接上传文件,都需要在请求头中使用Content-Type来告知,即带值multipart/form-data来进行上传文件
在这里插入图片描述

form-data传参

此时在post请求里已经不能传json了,要使用form-data。
此时在postman中的请求参数体,Body中新建一个key,名为file(可以任意一个key),然后将其文件格式设置为File,这时使用的文件格式,换成字符串Text也是允许的。
在这里插入图片描述
如果选择的是Text,在后面的Value中直接填写字符串就可以,这里选则的是File,所以在后面Value的位置,点击就可以选择文件,进行模拟传文件的操作。
在这里插入图片描述
随便选择一个文本文件查看效果使用
点击打开
在这里插入图片描述
在goland中敲入以下代码并运行:

package main

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


func main() {
    
	r := gin.Default() //启动gin路由,携带基础中间件启动 logger and recovery (crash-free) 中间件
	r.POST("testUpload", func(c *gin.Context) {
    
		file, _ := c.FormFile("file")
		c.JSON(200, gin.H{
    
			"msg":file,
		})
	})
	r.Run(":1010") // listen and serve on 0.0.0.0:8080
}

发起postman的请求:

在这里插入图片描述
在这里插入图片描述
可以看出,虽然返回的东西并不能看懂,但是已经成功返回了

保存文件

在goland中的返回JSON前添加以下语句,实现接收文件的存储,这里是将接收的文件保存在当前路径下,并使用上传时相同的文件名。

func main() {
    
	r := gin.Default() //启动gin路由,携带基础中间件启动 logger and recovery (crash-free) 中间件
	r.POST("testUpload", func(c *gin.Context) {
    
		file, _ := c.FormFile("file")
		c.SaveUploadedFile(file, "./"+file.Filename)
		c.JSON(200, gin.H{
    
			"msg":file,
		})
	})
	r.Run(":1010") // listen and serve on 0.0.0.0:8080
}

然后使用postman再次发起一个上传文件请求,
在这里插入图片描述
在这里插入图片描述
已经将文件保存下来,并经过对比与上传的文件无异
此处给出gin框架SaveUploadedFile实现的源码

// SaveUploadedFile uploads the form file to specific dst.
func (c *Context) SaveUploadedFile(file *multipart.FileHeader, dst string) error {
    
	src, err := file.Open()
	if err != nil {
    
		return err
	}
	defer src.Close()

	out, err := os.Create(dst)
	if err != nil {
    
		return err
	}
	defer out.Close()

	_, err = io.Copy(out, src)
	return err
}

然后将这个部分使用自己的方式进行实现

func main() {
    
	r := gin.Default() //启动gin路由,携带基础中间件启动 logger and recovery (crash-free) 中间件
	r.POST("testUpload", func(c *gin.Context) {
    
		file, _ := c.FormFile("file")
		in, _ := file.Open()
		defer in.Close()
		out, _ := os.Create("./"+file.Filename)
		defer out.Close()
		io.Copy(out, in)

		c.JSON(200, gin.H{
    
			"msg":file,
		})
	})
	r.Run(":1010") // listen and serve on 0.0.0.0:8080
}

这里和上面效果是一样得,不重复演示

附加参数

这里使用的是表单,那么之前学习的表单传参在这里依然适用。
将代码改变,增加name参数:

func main() {
    
	r := gin.Default() //启动gin路由,携带基础中间件启动 logger and recovery (crash-free) 中间件
	r.POST("testUpload", func(c *gin.Context) {
    
		file, _ := c.FormFile("file")
		name := c.PostForm("name")
		in, _ := file.Open()
		defer in.Close()
		out, _ := os.Create("./"+file.Filename)
		defer out.Close()
		io.Copy(out, in)

		c.JSON(200, gin.H{
    
			"msg":file,
			"name":name,
		})
	})
	r.Run(":1010") // listen and serve on 0.0.0.0:8080
}

在postman中增加name参数,并发起请求
在这里插入图片描述
在这里插入图片描述
不仅成功拿到了文件,还将name参数获取到了
通过这种方式,就可以将文件和其他信息混合传给后台
此处传图片也是可以的,因为追根揭底传送数据时都是以流的形式进行传递的,所以本质是一样的

将文件返回前端

单个文件

将代码进行改变

func main() {
    
	r := gin.Default() //启动gin路由,携带基础中间件启动 logger and recovery (crash-free) 中间件
	r.POST("testUpload", func(c *gin.Context) {
    
		file, _ := c.FormFile("file")
		in, _ := file.Open()
		defer in.Close()
		out, _ := os.Create("./"+file.Filename)
		defer out.Close()
		io.Copy(out, in)
		c.Writer.Header().Add("Content-Disposition", fmt.Sprintf("attachment; filename=%s", file.Filename))
		c.File("./"+file.Filename)
	})
	r.Run(":1010") // listen and serve on 0.0.0.0:8080
}

这里先直接给出postman请求结果
在这里插入图片描述
再给出图片的情况
在这里插入图片描述
函数c.Writer.Header().Add()在之后进行展开

批量文件

将代码修改如下:

func main() {
    
	r := gin.Default() //启动gin路由,携带基础中间件启动 logger and recovery (crash-free) 中间件
	r.POST("testUpload", func(c *gin.Context) {
    
		form,_ := c.MultipartForm()
		file := form.File["file"]
		fmt.Println(file)
	})
	r.Run(":1010") // listen and serve on 0.0.0.0:8080
}

这里仅大概体验下,具体实现就不给出了
postman进行请求
在这里插入图片描述
这里可以发现是两个流的形式,因为没设置返回,所以postman中无显示东西
为了更直观观察再次改变代码,增加一部分

func main() {
    
	r := gin.Default() //启动gin路由,携带基础中间件启动 logger and recovery (crash-free) 中间件
	r.POST("testUpload", func(c *gin.Context) {
    
		form,_ := c.MultipartForm()
		file := form.File["file"]
		fmt.Println(file)
		for _, f := range file{
    
			log.Println(f.Filename)
		}
	})
	r.Run(":1010") // listen and serve on 0.0.0.0:8080
}

在这里插入图片描述多文件可以通过循环实现存储,因为循环遍历时,每一次遍历都相当于处理单个文件

原网站

版权声明
本文为[一叶知秋@qqy]所创,转载请带上原文链接,感谢
https://blog.csdn.net/qq_41004932/article/details/119545949