当前位置: 首页 > news >正文

探索Gin框架:Golang使用Gin完成文件上传

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站https://www.captainbed.cn/kitie。

前言

在之前的文章中,我们讲解了Gin框架的快速入门使用,今天我们来聊聊如何使用Gin实现文件上传。

Go标准库net/http对文件上传已经提供了非常完善的支持,而Gin框架在其基础上进一步封装,因此使用Gin开发文件上传功能时,只需要简单几行代码便可以实现,Gin框架支持单个文件与多个文件同时上传。

目录

​编辑

前言

使用原生net/http库实现文件上传

使用Gin实现文件上传

单个文件上传

FormFile()获取文件

SaveUploadedFile()保存到本地 

设置缓冲区大小

限制文件大小

限制文件类型

完整示例

测试文件上传

多个文件上传

MultipartForm()获取多个文件

测试文件上传

总结


使用原生net/http库实现文件上传

我们首先看看实现一个HTTP服务器,提供文件上传功能的简单示例

package mainimport ("io""io/ioutil""log""net/http""github.com/julienschmidt/httprouter"
)const (MAX_UPLOAD_SIZE = 1024 * 1024 * 20 //最大上传大小,50MB
)func main() {r := RegisterHandlers()http.ListenAndServe(":8080", r)  // 开启一个http服务
}// 定义路由
func RegisterHandlers() *httprouter.Router {router := httprouter.New()router.POST("/upload", uploadHandler)return router
}
// 文件上传接口
func uploadHandler(w http.ResponseWriter, r *http.Request, p httprouter.Params) {r.Body = http.MaxBytesReader(w, r.Body, MAX_UPLOAD_SIZE)if err := r.ParseMultipartForm(MAX_UPLOAD_SIZE); err != nil {log.Printf("File is too big")return}file, headers, err := r.FormFile("file")if err != nil {log.Printf("Error when try to get file: %v", err)return}//获取上传文件的类型if headers.Header.Get("Content-Type") != "image/png" {log.Printf("只允许上传png图片")return}data, err := ioutil.ReadAll(file)if err != nil {log.Printf("Read file error: %v", err)return}fn := headers.Filenameerr = ioutil.WriteFile("./video/"+fn, data, 0666)if err != nil {log.Printf("Write file error: %v", err)return}w.WriteHeader(http.StatusCreated)io.WriteString(w, "Uploaded successfully")
}

如上我们通过r.FormFile函数获取上传的文件对象,以及文件的相关信息。然后通过headers.Header.Get函数获取上传文件的类型,判断类型是否符合要求。接着,使用ioutil.ReadAll函数读取文件的内容,并将其存储在data变量中。然后,通过headers.Filename获取上传文件的文件名,并使用ioutil.WriteFile函数将文件内容写入到指定路径下的文件中。

使用Gin实现文件上传

单个文件上传

FormFile()获取文件

单文件上传使用gin.ContextFormFile()方法,该方法的值为POST请求中文件上传字段的名称:

 engine := gin.Default()engine.POST("/upload", func(c *gin.Context) {file, err := c.FormFile("file")})engine.Run()

SaveUploadedFile()保存到本地 

调用gin.ContextSaveUploadedFile()方法可以将文件保存到某个目录下:

 dst := "./uploads/" + file.Filenamec.SaveUploadedFile(file,"./uploadFile")

设置缓冲区大小

Go默认文件上传缓冲区为32M,当有大量文件上传时,服务器内存的压力会很大,因此可以通过MaxMultipartMemory属性来设置缓冲区大小:

 //8Mengine.MaxMultipartMemory = 8 << 20

限制文件大小

上传文件时,不限制文件大小可以会导致服务存储空间暴涨,因为有必须限制上传文件大小:

 fileMaxSize := 4 << 20 //4Mif int(file.Size) > fileMaxSize {c.String(http.StatusBadRequest, "文件不允许大小于4M")return}

限制文件类型

对文件类型,也可以进行限制:

 reader, err := file.Open()if err != nil {fmt.Println(err)return}b := make([]byte, 512)reader.Read(b)​contentType := http.DetectContentType(b)if contentType != "image/jpeg" && contentType != "image/png" {c.String(http.StatusOK, "文件格式错误")return}

在上面的代码中,我们读取文件的前512个字节,再调用http.DetectContentType()便可以获取文件的MIME值。

完整示例

 package main​import ("fmt""log""net/http"​"github.com/gin-gonic/gin")​func main() {engine := gin.Default()//8Mengine.MaxMultipartMemory = 8 << 20engine.POST("/upload", func(c *gin.Context) {file, err := c.FormFile("file")if err != nil {log.Println(err)c.String(http.StatusBadRequest, "文件上传失败")return}fileMaxSize := 4 << 20 //4Mif int(file.Size) > fileMaxSize {c.String(http.StatusBadRequest, "文件不允许大小于32KB")return}​reader, err := file.Open()if err != nil {fmt.Println(err)return}b := make([]byte, 512)reader.Read(b)​contentType := http.DetectContentType(b)if contentType != "image/jpeg" && contentType != "image/png" {c.String(http.StatusOK, "文件格式错误")return}​dst := "./uploads/" + file.Filenamec.SaveUploadedFile(file, dst)c.String(http.StatusOK, fmt.Sprintf("'%s' 上传成功!", file.Filename))})engine.Run()}​

测试文件上传

$ curl -F "file=@./1.jpg" -X POST "http://localhost:8080/upload"'1.jpg' 上传成功!

多个文件上传

MultipartForm()获取多个文件

如果要上传多个文件,多次调用gin.ContextFormFile()方法也是可以的,但更好的方式是使用gin.ContextMultipartForm()方法:

 package main​import ("fmt""log""net/http"​"github.com/gin-gonic/gin")​func main() {engine := gin.Default()engine.POST("/uploadMul", func(c *gin.Context) {form, err := c.MultipartForm()if err != nil {log.Println(err)c.String(http.StatusBadRequest, "文件上传失败")return}files := form.File["upload"]for _, file := range files {fmt.Println(file.Filename)}c.String(http.StatusOK, fmt.Sprintf("%d files uploaded!", len(files)))})engine.Run()}

测试文件上传

运行程序后,使用curl命令上传多个文件:

$ curl -F "upload=@./1.jpg" -F "upload=@./2.jpg" -X POST "http://localhost:8080/uploadMul
2 files uploaded

总结

Go标准库net/http对文件上传已经提供了非常完善的支持,可以满足我们大部分需求,Gin框架在其基础做了封装,让我们使用起来更加方便迅速。

感谢阅读~

相关文章:

  • 深度学习如何入门?
  • RabbitMQ面试
  • 【云原生kubernetes系列】---亲和与反亲和
  • 《区块链简易速速上手小册》第7章:区块链在其他行业的应用(2024 最新版)
  • leetcode189.轮转数组|超简单易于理解方法
  • Elasticsearch:如何为 Elastic Stack 配置 AI Assistant
  • ElementUI 组件:Container 布局容器实例
  • C# WebServices代理类
  • 面试经典 150 题 -- 数组 / 字符串 (总结)
  • 【Spring连载】使用Spring Data访问Redis(十四)----Redis Repositories
  • 【中国善网ESG周报】企业ESG报告分析之“美的”
  • jupyter notebook显示的扩展很少,只有四五个--解决方案
  • ROS中的GPS RTK 坐标轨迹可视化
  • 猫什么时候发腮?猫咪发腮指南!这些生骨肉冻干发腮效果好
  • LeetCode:283. 移动零
  • ----------
  • JavaScript-如何实现克隆(clone)函数
  • 【许晓笛】 EOS 智能合约案例解析(3)
  • 【跃迁之路】【735天】程序员高效学习方法论探索系列(实验阶段492-2019.2.25)...
  • JavaScript DOM 10 - 滚动
  • js算法-归并排序(merge_sort)
  • JS专题之继承
  • linux安装openssl、swoole等扩展的具体步骤
  • Spring声明式事务管理之一:五大属性分析
  • UEditor初始化失败(实例已存在,但视图未渲染出来,单页化)
  • Vue学习第二天
  • 简单数学运算程序(不定期更新)
  • 那些年我们用过的显示性能指标
  • 小李飞刀:SQL题目刷起来!
  • 在electron中实现跨域请求,无需更改服务器端设置
  • # 日期待t_最值得等的SUV奥迪Q9:空间比MPV还大,或搭4.0T,香
  • # 睡眠3秒_床上这样睡觉的人,睡眠质量多半不好
  • #微信小程序:微信小程序常见的配置传值
  • (NO.00004)iOS实现打砖块游戏(十二):伸缩自如,我是如意金箍棒(上)!
  • (pojstep1.3.1)1017(构造法模拟)
  • (二)基于wpr_simulation 的Ros机器人运动控制,gazebo仿真
  • (规划)24届春招和25届暑假实习路线准备规划
  • (三十五)大数据实战——Superset可视化平台搭建
  • (转)Oracle存储过程编写经验和优化措施
  • (转)可以带来幸福的一本书
  • .NET MVC之AOP
  • .net2005怎么读string形的xml,不是xml文件。
  • .net操作Excel出错解决
  • .net和php怎么连接,php和apache之间如何连接
  • .net经典笔试题
  • .net实现头像缩放截取功能 -----转载自accp教程网
  • .ui文件相关
  • /3GB和/USERVA开关
  • @Autowired自动装配
  • @transaction 提交事务_【读源码】剖析TCCTransaction事务提交实现细节
  • [20160902]rm -rf的惨案.txt
  • [23] GaussianAvatars: Photorealistic Head Avatars with Rigged 3D Gaussians
  • [Android]使用Android打包Unity工程
  • [BetterExplained]书写是为了更好的思考(转载)
  • [C#] 我的log4net使用手册