Gin从入门到精通(七)文件上传和下载
- 其他
- 2025-09-18 15:36:01

文件上传和下载 1.文件上传 1.1单文件上传
在 Gin 中处理单文件上传,可以使用 c.FormFile 方法获取上传的文件,然后使用 c.SaveUploadedFile 方法保存文件。
package main import ( "github /gin-gonic/gin" "log" ) func main() { r := gin.Default() r.POST("/upload", func(c *gin.Context) { // 获取名为 "file" 的上传文件 file, err := c.FormFile("file") if err != nil { c.JSON(400, gin.H{"error": err.Error()}) return } // 保存上传的文件 if err := c.SaveUploadedFile(file, file.Filename); err != nil { log.Println("Failed to save file:", err) c.JSON(500, gin.H{"error": "Failed to save file"}) return } c.JSON(200, gin.H{ "message": "File uploaded successfully", "filename": file.Filename, }) }) r.Run(":8080") }我们使用postman来提交,http://localhost:8080/upload
1.2多文件上传处理多文件上传时,可以使用 c.MultipartForm 方法获取所有上传的文件。
package main import ( "github /gin-gonic/gin" "log" ) func main() { r := gin.Default() r.POST("/multi-upload", func(c *gin.Context) { // 获取所有上传的文件 form, err := c.MultipartForm() if err != nil { c.JSON(400, gin.H{"error": err.Error()}) return } files := form.File["files"] for _, file := range files { // 保存每个上传的文件 if err := c.SaveUploadedFile(file, file.Filename); err != nil { log.Println("Failed to save file:", err) c.JSON(500, gin.H{"error": "Failed to save file"}) return } } c.JSON(200, gin.H{ "message": "Files uploaded successfully", "count": len(files), }) }) r.Run(":8080") }使用postman测试,http://localhost:8080/multi-upload
1.3 限制上传文件大小Gin 默认允许上传 32 MiB 的文件,可通过 router.MaxMultipartMemory 调整:
package main import ( "fmt" "github /gin-gonic/gin" "log" "net/http" "path/filepath" "strings" ) func main() { r := gin.Default() // 设置全局上传限制(可选) // 注意:Gin 默认的 MaxMultipartMemory 是 32 MiB r.MaxMultipartMemory = 10 << 20 // 10 MiB r.POST("/upload", func(c *gin.Context) { // 获取名为 "file" 的上传文件 file, err := c.FormFile("file") // 校验文件大小(10MB = 10 * 1024 * 1024 bytes) maxSize := r.MaxMultipartMemory if file.Size > maxSize { c.JSON(http.StatusRequestEntityTooLarge, gin.H{ "error": fmt.Sprintf("文件大小超过限制(最大 %dMB)", maxSize/(1<<20)), }) return } if err != nil { c.JSON(400, gin.H{"error": err.Error()}) return } //r.MaxMultipartMemory = 1 << 20 // 1 MiB // 保存上传的文件 if err := c.SaveUploadedFile(file, file.Filename); err != nil { log.Println("Failed to save file:", err) c.JSON(500, gin.H{"error": "保存文件失败"}) return } c.JSON(200, gin.H{ "message": "File uploaded successfully", "filename": file.Filename, }) }) r.Run(":8080") } 1.4 限制上传文件类型限制文件类型很简单,就是检测上传文件后缀 , 为了避免上传可执行文最好再校验MIME 类型
package main import ( "fmt" "github /gin-gonic/gin" "log" "net/http" "path/filepath" "strings" ) func isAllowedType(filename string) bool { allowed := map[string]bool{ ".jpg": true, ".png": true, } ext := strings.ToLower(filepath.Ext(filename)) return allowed[ext] } func main() { r := gin.Default() // 设置全局上传限制(可选) // 注意:Gin 默认的 MaxMultipartMemory 是 32 MiB r.MaxMultipartMemory = 10 << 20 // 10 MiB r.POST("/upload", func(c *gin.Context) { // 获取名为 "file" 的上传文件 file, err := c.FormFile("file") // 在接口中调用校验 if !isAllowedType(file.Filename) { c.JSON(http.StatusBadRequest, gin.H{"error": "不支持的文件类型"}) return } if err != nil { c.JSON(400, gin.H{"error": err.Error()}) return } //r.MaxMultipartMemory = 1 << 20 // 1 MiB // 保存上传的文件 if err := c.SaveUploadedFile(file, file.Filename); err != nil { log.Println("Failed to save file:", err) c.JSON(500, gin.H{"error": "保存文件失败"}) return } c.JSON(200, gin.H{ "message": "File uploaded successfully", "filename": file.Filename, }) }) r.Run(":8080") } 1.5 避免上传文件名冲突为了避免文件名冲突通常使用 UUID 或时间戳重命名,这里我们演示下 uuid
安装uuid库:
go get github /google/uuid具体实现:
//<pre> // 生成唯一文件名</pre> newFilename := uuid.New().String() + filepath.Ext(file.Filename) if err := c.SaveUploadedFile(file, newFilename); err != nil { log.Println("Failed to save file:", err) c.JSON(500, gin.H{"error": "保存文件失败"}) return } 2.文件下载 2.1 单文件下载下载很简单,使用 c.File()即可,下面是演示代码:
package main import ( "github /gin-gonic/gin" "net/http" "os" ) func main() { r := gin.Default() // 文件下载 r.GET("/download/:filename", func(c *gin.Context) { filename := c.Param("filename") filePath := "./img/" + filename if _, err := os.Stat(filePath); os.IsNotExist(err) { c.JSON(http.StatusNotFound, gin.H{"error": "文件不存在"}) return } //c.Header("Content-Disposition", "attachment; filename="+filename) c.File(filePath) }) r.Run(":8080") } 2.2 设置浏览器头信息如果你是用来图片文件,来测试上面的代码,你会发现浏览器是直接显示图片,而不是下载图片,所以我们需要使浏览器唤起下载行为。
通过 Content-Disposition 头强制浏览器下载文件(而非预览):
c.Header("Content-Type", "application/octet-stream") // 表示是文件流,唤起浏览器下载,一般设置了这个,就要设置文件名 c.Header("Content-Disposition", "attachment; filename="+filename) 用来指定下载下来的文件名 c.Header("Content-Transfer-Encoding", "binary") // 表示传输过程中的编码形式,乱码问题可能就是因为它 c.File(filePath)Gin从入门到精通(七)文件上传和下载由讯客互联其他栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“Gin从入门到精通(七)文件上传和下载”
上一篇
蓝桥与力扣刷题(蓝桥核桃的数量)