Go Gin文件流式上传下载实战 | 避免内存溢出的高性能方案
目录
文件上传
Go + Gin 实现文件上传保存
在业务开发过程中,经常会遇到文件上传到服务器的需求,常规的文件上传一般不会存在文件,但是当出现大文件上传时,如果代码写的不好,容易导致服务器 OOM,这时候可以使用 Go + Gin 文件上传方案,实现大文件流式上传,避免整个文件加载到内存导致 OOM 代码如下:
package main
import (
github.com/gin-gonic/gin
)
func main(){
r := gin.Default()
r.Use(gin.Recovery())
r.POST("upload",func(c *gin.Context) { // 本质上就是一个 POST 表单接口,其中 file 参数一般是固定的,可以自定义其他的前端参数
fileHeader, err := c.FormFile("file") // 读取文件信息
if err!=nil{
// 响应错误信息
return
}
savePath:="/home/save.png" // 文件保存的路径
// 保存文件
err = c.SaveUploadedFile(fileHeader, savePath)
if err != nil {
return nil, err
}
})
r.Run(":8080")
}
几行代码即可实现大文件保存,c.SaveUploadedFile 的原理也很简单,通过流式批量读取上传的文件(一次可能就读取几M),先保存到临时文件,最后再完成保存,删除临时文件
常见错误: Q1:SaveUploadedFile报错"http: no such file"? A:检查表单enctype是否为
multipart/form-data
文件下载
go + gin 实现服务器文件下载也很非常简单,代码如下:
package main
import (
github.com/gin-gonic/gin
)
func main(){
r := gin.Default()
r.Use(gin.Recovery())
r.GET("download",func(c *gin.Context) { // 本质上就是一个普通的接口,像文件名、文件路径可以作为前端参数上传
filePath:="/home/save.png" // 文件路径
fileName:="save.png" // 下载展示的文件名称
// 设置Content-Disposition触发浏览器下载(非展示)
c.Writer.Header().Set("Content-Disposition", "attachment; filename="+fileName)
c.Writer.Header().Set("Content-Type", "application/octet-stream")
// 下载
c.File(filePath)
})
r.Run(":8080")
}
```tet-stream")
// 下载
c.File(filePath)
})
r.Run(":8080")
}