前言
感谢开源项目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
}
多文件可以通过循环实现存储,因为循环遍历时,每一次遍历都相当于处理单个文件