探索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框架在其基础做了封装,让我们使用起来更加方便迅速。

感谢阅读~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/662329.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

golang的sqlite驱动不使用cgo实现 更换gorm默认的SQLite驱动

golang的sqlite驱动不使用cgo实现 更换gorm默认的SQLite驱动 最近在开发一个边缘物联网程序时使用Golang开发&#xff0c;用到GORM来操作SQLite数据库&#xff0c;GORM默认使用gorm.io/driver/sqlite这个库作为SQLite驱动&#xff0c;该库用CGO实现&#xff0c;在使用过程中遇…

OpenAI Gym 中级教程——多智能体系统

Python OpenAI Gym 中级教程&#xff1a;多智能体系统 在强化学习中&#xff0c;多智能体系统涉及到多个智能体相互作用的情况。在本篇博客中&#xff0c;我们将介绍如何在 OpenAI Gym 中构建和训练多智能体系统&#xff0c;并使用 Multi-Agent Deep Deterministic Policy Gra…

Unity_Shader

Unity_Shader 目录 Unity_Shader 带着问题开始: Shader Graph 开始吧!

【NLP冲吖~】一、朴素贝叶斯(Naive Bayes)

0、朴素贝叶斯法 朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法。对于给定的训练数据集&#xff0c;首先基于特征条件独立假设学习输入输出的联合概率分布&#xff0c;然后基于此模型&#xff0c;对给定的输入 x x x&#xff0c;利用贝叶斯定理求出后验概率最大的…

【Spring Boot 3】应用启动执行特定逻辑

【Spring Boot 3】应用启动执行特定逻辑 背景介绍开发环境开发步骤及源码工程目录结构总结背景 软件开发是一门实践性科学,对大多数人来说,学习一种新技术不是一开始就去深究其原理,而是先从做出一个可工作的DEMO入手。但在我个人学习和工作经历中,每次学习新技术总是要花…

element-ui button 仿写 demo

基于上篇 button 源码分享写了一个简单 demo&#xff0c;在写 demo 的过程中&#xff0c;又发现了一个小细节&#xff0c;分享一下&#xff1a; 1、组件部分&#xff1a; <template><buttonclass"yss-button"click"handleClick":class"[ty…

STM32目录结构

之前一直头疼的32目录&#xff0c;比51复杂&#xff0c;又没有C规律&#xff0c;也不像python脚本文件关联不强&#xff0c;也不像工整的FPGA工程&#xff0c;编的时候到处放&#xff0c;爆出的错千奇百怪。短暂整理了一个&#xff0c;还是没有理得很轻。 startup_stm32f10x_m…

基于python+django,我开发了一款药店信息管理系统

功能介绍 平台采用B/S结构&#xff0c;后端采用主流的Python语言进行开发&#xff0c;前端采用主流的Vue.js进行开发。 功能包括&#xff1a;药品管理、分类管理、顾客管理、用户管理、日志管理、系统信息模块。 代码结构 server目录是后端代码web目录是前端代码 部署运行…

2024年1月29日-2月4日(全面进行+收集虚幻商城免费资源)

从上周发现&#xff0c;一轮轮推就行&#xff0c;每轮多个时间片&#xff0c;每个时间片一门。周一到周五一轮&#xff0c;周六日多轮&#xff08;比如上下午各一轮&#xff09;。 周一&#xff1a; 7&#xff1a;09–9&#xff1a;20卫星导航定位&#xff08;p3&#xff09;&a…

基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖(十六)

商家端订单管理模块 1. 订单搜索1.1 需求分析和设计1.2 代码实现1.2.1 admin/OrderController1.2.2 OrderService1.2.3 OrderServiceImpl 2. 各个状态的订单数量统计2.1 需求分析和设计2.2 代码实现2.2.1 admin/OrderController2.2.2 OrderService2.2.3 OrderServiceImpl2.2.4 …

浅谈UI自动化测试

为了让对自动化技术感兴趣的朋友们有真实案例的支持&#xff0c;今天我们给大家带来一期适合新手的UI自动化测试介绍。我们的目标是让大家能够轻松理解UI自动化测试的概念&#xff0c;并且能够亲自动手去实践。通过这个介绍&#xff0c;大家能够对UI自动化测试有一个整体的理解…

Python:列表、元组和字典

3.1 序列简介 所谓序列&#xff0c;指的就是一种包含多项数据的数据结构&#xff0c;序列包含的多个数据项&#xff08;也叫成员&#xff09;按顺序排列&#xff0c;可通过索引来访问成员。 3.1.1 python的序列 python的常见序列类型包括字符串、列表 和元组等。 列表和元组…

HTML 相关知识点记录

<div> </div> DIV标签详细介绍-CSDN博客 div 是 division 的简写&#xff0c;division 意为分割、区域、分组。比方说&#xff0c;当你将一系列的链接组合在一起&#xff0c;就形成了文档的一个 division。 <p>标签&#xff1a;定义段落

【Linux C | I/O模型】Unix / Linux系统的5种IO模型 | 图文详解

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

2016年苏州大学837复试机试C/C++

2016年苏州大学复试机试 第一题 题目 公鸡5元一只&#xff0c;母鸡3元一只&#xff0c;幼鸡1元3只。若100元钱买了100只鸡&#xff0c;问其中公鸡、母鸡、幼鸡各多少只&#xff1f; 博主注&#xff1a;此题经典百元买百鸡问题&#xff0c;出自&#xff1a;公元5世纪末&#…

2024数学建模美赛选题建议及各题思路来了

大家好呀&#xff0c;美赛数学建模开始了&#xff0c;来说一下初步的选题建议吧&#xff1a; 首先定下主基调&#xff0c;本次亚太杯推荐选择C题/F题。 ABD题较为硬核&#xff0c;仅推荐有相关专业背景的人选择&#xff0c;E题需要搜集的数据以及对于数据的要求极高&#xff…

模拟钉钉官网动画

实现思路&#xff1a;利用粘性定位sticky&#xff0c;以及滚动事件实现。首先我们应该设置滚动动画开始位置和结束位置 &#xff0c;然后根据位置计算透明度或者transform&#xff0c;scale的值。 首先根据上述图线计算属性值&#xff0c;代码如下&#xff1a; function creat…

PHP漏洞查询

CVE - Search CVE List (mitre.org) 美国国家漏洞数据库&#xff08;需要梯子&#xff09; NATIONAL VULNERABILITY DATABASE NVD - Search and Statistics (nist.gov) 基本都能查询到&#xff0c;传结果详情页里面会有一些解决方案的连接 PHP的官方网站 PHP :: Bugs :: Se…

C语言探索:水仙花数的奥秘与计算

摘要&#xff1a; 水仙花数&#xff0c;一种特殊的三位数&#xff0c;其各位数字的立方和等于该数本身。本文将详细介绍水仙花数的定义、性质&#xff0c;以及如何使用C语言来寻找100至999范围内的水仙花数。 目录 一、水仙花数的定义与性质 二、用C语言寻找100至999范围内的…

Camunda 流程引擎API介绍

&#x1f496;专栏简介 ✔️本专栏将从Camunda(卡蒙达) 7中的关键概念到实现中国式工作流相关功能。 ✔️文章中只包含演示核心代码及测试数据&#xff0c;完整代码可查看作者的开源项目snail-camunda ✔️请给snail-camunda 点颗星吧&#x1f618; &#x1f496;Services …