Golang Gin框架HTTP上传文件
Golang Gin框架HTTP上传文件解析
文章目录
- Golang Gin框架HTTP上传文件解析
- HTTP上传的文件的原理
- Gin框架文件上传Demo
- 限制文件上传的大小
- 文件类型验证
- 文件上传进度-后台计算文件上传进度
HTTP上传的文件的原理
HTTP协议的文件上传是通过HTTP POST请求实现的,使用multipart/form-data格式将待上传的文件放入请求体中。
服务器根据请求头中的boundary参数来解析请求体,并根据Content-Disposition字段获取文件名等信息,根据Content-Type字段判断文件类型并保存到相应位置。
Gin框架文件上传Demo
代码逻辑:
- 通过Gin框架封装的Form表单获取数据,获取上传文件
- 获取文件名,并创建新的文件存储
- 将上传的文件内容写入新的文件
- 返回上传成功信息
package mainimport ("fmt""github.com/gin-gonic/gin""io""net/http""os"
)func uploadFile(c *gin.Context) {//form表单file, header, err := c.Request.FormFile("upload")if err != nil {c.String(http.StatusBadRequest, fmt.Sprintf("上传文件失败: %s", err.Error()))return}// 获取文件名,并创建新的文件存储filename := header.Filenameout, err := os.Create(filename)if err != nil {c.String(http.StatusBadRequest, fmt.Sprintf("创建文件: %s", err.Error()))return}defer out.Close()//将读取的文件流写到文件中_, err = io.Copy(out, file)if err != nil {c.String(http.StatusBadRequest, fmt.Sprintf("读取文件失败: %s", err.Error()))return}c.String(http.StatusCreated, "上传成功 \n")
}func main() {router := gin.Default()//路由:http://localhost:8080/uploadrouter.POST("/upload", uploadFile)router.Run(":8080")
}
限制文件上传的大小
使用 http.MaxBytesReader() 函数来限制 HTTP 请求中读取的最大字节数。这个函数会返回一个新的 Reader 对象,该对象会在读取请求的正文时自动检查字节数,如果超过指定的最大字节数,则会自动停止读取,返回错误。
//限制大小为2M
c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, int64(2<<20))file, header, err := c.Request.FormFile("upload")if err != nil {c.String(http.StatusBadRequest, fmt.Sprintf("上传文件失败: %s", err.Error()))return}
该代码不能限制文件上传大小,只是设置内存大小,即使文件大小比这个大,也会写入临时文件
router := gin.Default()
router.MaxMultipartMemory = 2 * 1024 //2M Byte,默认32M
运行结果截图

文件类型验证
验证上传的文件类型,以确保上传的文件是我们期望的类型,借助“github.com/h2non/filetype”实现对文件类型的判断
import ("fmt""github.com/gin-gonic/gin""github.com/h2non/filetype""io""net/http"
)
func uploadFile(c *gin.Context) {//form表单c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, int64(2<<20))file, _, err := c.Request.FormFile("upload")if err != nil {c.String(http.StatusBadRequest, fmt.Sprintf("上传文件失败: %s", err.Error()))return}content, err := io.ReadAll(file)if err != nil {c.String(http.StatusBadRequest, fmt.Sprintf("读取失败: %s", err.Error()))return}// 解析文件类型kind, err := filetype.Match(content)if err != nil {c.String(http.StatusBadRequest, fmt.Sprintf("文件类型判断失败: %s", err.Error()))return}fmt.Println(kind)// 验证文件类型if kind == filetype.Unknown {c.String(http.StatusCreated, "未知类型 \n")return}if filetype.IsImage(content) {c.String(http.StatusCreated, "图片 上传成功 \n")return}c.String(http.StatusCreated, "上传成功 \n")
}

文件上传进度-后台计算文件上传进度
实现原理:
要实现 Gin 框架中的文件上传进度,在文件上传中,计算已上传的字节数,并将其与文件的总大小进行比较,以确定上传的进度。
package mainimport ("fmt""github.com/gin-gonic/gin""net/http""os"
)func uploadFile(c *gin.Context) {//form表单//c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, int64(2<<20))file, fileHeader, err := c.Request.FormFile("upload")if err != nil {c.String(http.StatusBadRequest, fmt.Sprintf("上传文件失败: %s", err.Error()))return}filename := fileHeader.Filenameout, err := os.Create(filename)if err != nil {c.String(http.StatusBadRequest, fmt.Sprintf("创建文件: %s", err.Error()))return}defer out.Close()count := 0for {buf := make([]byte, 10000)n, err := file.Read(buf)if err != nil {c.String(http.StatusBadRequest, fmt.Sprintf("读取失败: %s", err.Error()))return}if n == 0 {break}count = count + nout.Write(buf)fmt.Println(count, float64(fileHeader.Size))progress := float64(count) / float64(fileHeader.Size) * 100fmt.Println(fmt.Sprintf("%.2f%%", progress))}c.String(http.StatusCreated, "上传成功 \n")
}func main() {router := gin.Default()router.MaxMultipartMemory = 2 * 1024 //2M Byte,默认32M//路由:http://localhost:8080/uploadrouter.POST("/upload", uploadFile)fmt.Println(router.MaxMultipartMemory)router.Run(":8080")
}相关文章:
Golang Gin框架HTTP上传文件
Golang Gin框架HTTP上传文件解析 文章目录Golang Gin框架HTTP上传文件解析HTTP上传的文件的原理Gin框架文件上传Demo限制文件上传的大小文件类型验证文件上传进度-后台计算文件上传进度HTTP上传的文件的原理 HTTP协议的文件上传是通过HTTP POST请求实现的,使用mult…...
BM36-判断是不是平衡二叉树
题目 输入一棵节点数为 n 二叉树,判断该二叉树是否是平衡二叉树。 在这里,我们只需要考虑其平衡性,不需要考虑其是不是排序二叉树 平衡二叉树(Balanced Binary Tree),具有以下性质:它是一棵空…...
Quartz 单例定时任务
1、引入jar包,继承 Job 接口,编写需要执行的业务逻辑 <dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.3.2</version></dependency> public class D…...
不要告诉同事你要离职!打算跳槽,新公司开出两倍薪资,私下告诉要好的同事,却被同事出卖给领导!...
职场上有真正的朋友吗?来看看这位网友的讲述:一位前同事本来打算跳槽,新公司开出的薪资是原来的两倍。她私下告诉了几位同事自己打算离职的消息,并跟同事们分享了工资翻倍的喜悦。可她万万没想到,两天之后的公司会议上…...
RK3399平台开发系列讲解(外设篇)Camera OV13850配置过程
🚀返回专栏总目录 文章目录 一、DTS 配置二、驱动说明三、配置原理四、cam_board.xml沉淀、分享、成长,让自己和他人都能有所收获!😄 📢我们以 OV13850/OV5640 摄像头为例,讲解在该开发板上的配置过程。 一、DTS 配置 isp0: isp@ff910000 {…status = "okay&quo…...
yolov8训练自己的数据集
yolov8训练自己的数据集 1. 标注自己的数据集1.1 确认标注格式1.2 开始标注1. 标注自己的数据集 1.1 确认标注格式 YOLOv8 所用数据集格式与 YOLOv5 YOLOv7 相同,采用格式如下: <object-class-id> <x> <y> <width> <height...
【产品经理】对接第三方平台,你应该怎么做?
作为产品经理,有时候你会接到需求、要求处理对接第三方平台的工作,那么你知道如何判断该不该接这个需求、如何处理第三方平台的对接工作吗? 一、Why 首先是为什么要选择对接第三方平台,这不是一个拍脑袋就可以做决定的事情&#…...
Hbase 介绍
Hbase 简介 Hbase 是一个开源的非关系型的分布式数据库,运用于HDFS文件系统之上,可以容错地存储海量稀疏的数据。Hbase是一个高可靠、高性能、面向列、可伸缩、实时读写的分布式数据库,主要用来存储非结构化和半结构化的松散数据 。 Hbase的…...
金三银四没把握住,凉了...
大家好,前两天跟朋友感慨,今年的铜三铁四、裁员、疫情导致好多人都没拿到offer!现在互联网大厂终于迎来了应届生集中求职季。 对于想跳槽的软件测试人来说,绝对是个找工作的好时机。这时候,很多高薪技术岗、管理岗的缺口和市场需…...
模拟axios请求的数据Mockjs在vue3的使用
1.安装mockjs和axios cnpm install mockjs -Scnpm install axios -S目录结构(这里的演示只用到这四个文件) 2.创建模拟返回的数据(src/mockjs/http.js),放入以下内容 //模拟的请求数据 export default {getData: () > {return {code: 200,tableData: [{id: "01",…...
Elasticsearch:索引状态是红色还是黄色?为什么?
在我之前文章 “Elasticsearch:如何调试集群状态 - 定位错误信息” 中,我有详细介绍如何调试集群状态。在今天的文章中,我将详细介绍如何故障排除和修复索引状态。 Elasticsearch 是一个伟大而强大的系统,特别是创建一个可扩展性极…...
一对多关系映射
在MyBatis中,可以使用XML文件或者注解来进行关系映射。其目的就是将Java对象和数据库表进行映射,从而可以方便地进行数据的操作。 MyBatis关系映射数据库表到Java对象的映射SQL语句到Java方法的映射定义Java类,在XML文件中定义这个Java类和数据库表之间的映射关系定义Java方…...
字母有重复全排列 [2*]
目录 字母有重复全排列 [2*] 程序设计 程序分析 字母有重复全排列 [2*] 输出前N个字母的有重复全排列 Input 输入一个数值N 1<=N<=10 Output 输出前N个大写字母的有重复全排列 Sample Input 2 Sample Output...
机器学习中的数学原理——过拟合、正则化与惩罚函数
通过这篇博客,你将清晰的明白什么是过拟合、正则化、惩罚函数。这个专栏名为白话机器学习中数学学习笔记,主要是用来分享一下我在 机器学习中的学习笔记及一些感悟,也希望对你的学习有帮助哦!感兴趣的小伙伴欢迎私信或者评论区留言…...
RK3588S imx415摄像头调试
一、环境 soc:rk3588sensor:imx415board: AIO-3588SJDlinux:rk3588_linux_release_20230301_v1.0.6e 二、imx415简介 品牌:SONY型号:IMX415接口:MIPI CSI 三、驱动移植 瑞芯微支持的摄像头,有…...
「SAP ABAP」OPEN SQL(七)【GROUP BY | HAVING | ORDER BY】
💂作者简介: THUNDER王,一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学本科在读,同时任汉硕云(广东)科技有限公司ABAP开发顾问。在学习工作中,我通常使用偏后端的开发语言A…...
容器-LinkedList
LinkedList LinkedList的概述 LinkedList的底层使用双向链表实现。 链表是一种线性数据结构,其中每个元素都是一个单独的对象,包含一个指向列表中下一个节点的引用。 它可以用于实现各种抽象数据类型,例如列表、堆栈、队列等。 LinkedLis…...
Flask 路由和视图函数
Flask 路由和视图函数一、路由 (Routing)二、视图函数 (View Functions)三、动态路由四、HTTP方法五、总结在Flask中,路由和视图函数是两个核心概念,它们协同工作以处理用户请求并生成响应。一、路由 (Routing) 路由是URL到Python函数的映射。当用户访问…...
Linux主机 SSH 通过密钥登录
我们一般使用 PuTTY 等 SSH 客户端来远程管理 Linux 服务器。但是,一般的密码方式登录,容易有密码被暴力破解的问题。所以,一般我们会将 SSH 的端口设置为默认的 22 以外的端口,或者禁用 root 账户登录。其实,有一个更…...
中国信息安全测评中心-自主原创测评
信息技术产品自主原创测评是适应我国经济社会发展的需要,是适应国际知识产权保护的发展趋势,鼓励信息技术产业的自主创新和维护权利人合法权益的重要举措。 信息技术产品自主原创测评业务是指在开发者自主声明的基础上,通过对关键技术实现的全…...
19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...
学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...
go 里面的指针
指针 在 Go 中,指针(pointer)是一个变量的内存地址,就像 C 语言那样: a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10,通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...
git: early EOF
macOS报错: Initialized empty Git repository in /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/.git/ remote: Enumerating objects: 2691797, done. remote: Counting objects: 100% (1760/1760), done. remote: Compressing objects: 100% (636/636…...
数据结构:递归的种类(Types of Recursion)
目录 尾递归(Tail Recursion) 什么是 Loop(循环)? 复杂度分析 头递归(Head Recursion) 树形递归(Tree Recursion) 线性递归(Linear Recursion)…...
