Go学习第十六章——Gin文件上传与下载

Go web框架——Gin文件上传与下载

    • 1. 文件上传
      • 1.1 入门案例(单文件)
      • 1.2 服务端保存文件的几种方式
        • SaveUploadedFile
        • Create+Copy
      • 1.3 读取上传的文件
      • 1.4 多文件上传
    • 2. 文件下载
      • 2.1 快速入门
      • 2.2 前后端模式下的文件下载
      • 2.3 中文乱码问题

1. 文件上传

1.1 入门案例(单文件)

func main() {router := gin.Default()// 为 multipart forms 设置较低的内存限制 (默认是 32 MiB)// 单位是字节, << 是左移预算符号,等价于 8 * 2^20// gin对文件上传大小的默认值是32MB// 1. 设置路由器的最大内存限制为8MB,用于处理multipart表单数据中的文件上传。router.MaxMultipartMemory = 8 << 20 // 8 MiB// 2. 定义一个路由处理函数router.POST("/upload", func(c *gin.Context) {// 单文件// 3.通过c.FormFile函数获取HTTP请求上传的文件对象。//   其中参数"file"是上传表单中文件类型的name属性值。file, _ := c.FormFile("file")// 使用log包打印上传的文件名。log.Println(file.Filename)// 4. 指定上传文件的目标完整路径dst := "./" + file.Filename// 5. 使用c.SaveUploadedFile函数保存文件到指定路径下。c.SaveUploadedFile(file, dst)// 6. 使用c.String函数向客户端响应上传成功信息。c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))})router.Run(":8000")
}

image-20231028210743918

1.2 服务端保存文件的几种方式

SaveUploadedFile
func (c *Context) SaveUploadedFile(file *multipart.FileHeader, dst string) error

SaveUploadedFile函数用于将文件保存到指定的路径下。第一个参数是文件对象,第二个参数是保存文件的路径。

Create+Copy
func (c *Context) FormFile(name string) (*multipart.FileHeader, error)

FormFile函数用于获取上传的文件。它返回一个文件对象,其中包含了文件的元数据(名称、大小等)。我们可以使用这个文件对象去直接读取文件内容。

func main() {router := gin.Default()router.MaxMultipartMemory = 8 << 20 // 8 MiBrouter.POST("/upload", func(c *gin.Context) {file, _ := c.FormFile("file")log.Println(file.Filename)// 读取文件中的数据,返回文件对象fileRead, _ := file.Open()dst := "./" + file.Filename// 创建一个文件out, err := os.Create(dst)if err != nil {fmt.Println(err)}defer out.Close()// 拷贝文件对象到out中io.Copy(out, fileRead)c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))})router.Run(":8000")
}

一样是使用Apifox调用,没有什么毛病~

1.3 读取上传的文件

func (c *Context) FormFile(name string) (*multipart.FileHeader, error)

FormFile函数用于获取上传的文件。它返回一个文件对象,其中包含了文件的元数据(名称、大小等)。我们可以使用这个文件对象去直接读取文件内容。

func main() {router := gin.Default()router.MaxMultipartMemory = 8 << 20 // 8 MiBrouter.POST("/upload", func(c *gin.Context) {file, _ := c.FormFile("file")// 读取文件中的数据,返回文件对象fileRead, _ := file.Open()defer fileRead.Close()data, _ := io.ReadAll(fileRead)fmt.Println(string(data))c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))})router.Run(":8000")
}

在这里我们可以根据文件的内容来判断是否需要保存到服务器中。

1.4 多文件上传

func (c *Context) MultipartForm() (*multipart.Form, error)

MultipartForm函数用于获取上传的表单数据。它返回一个包含了文件对象的表单对象。

func main() {router := gin.Default()// 为 multipart forms 设置较低的内存限制 (默认是 32 MiB)router.MaxMultipartMemory = 8 << 20 // 8 MiBrouter.POST("/upload", func(c *gin.Context) {// Multipart formform, _ := c.MultipartForm()files := form.File["upload[]"]  // 注意这里名字不要对不上了for _, file := range files {log.Println(file.Filename)// 上传文件至指定目录c.SaveUploadedFile(file, "./"+file.Filename)}c.String(http.StatusOK, fmt.Sprintf("%d files uploaded!", len(files)))})router.Run(":8000")
}

2. 文件下载

2.1 快速入门

直接响应一个路径下的文件

func main() {router := gin.Default()router.GET("/download", func(c *gin.Context) {c.File("思考一个问题的四连问.txt")})router.Run(":8000")
}

然后,直接在游览器访问,就能下载到了!!

image-20231028212634272

但是呐:

有些响应,比如图片,浏览器就会显示这个图片,而不是下载,所以我们需要使浏览器唤起下载行为

c.Header("Content-Type", "application/octet-stream") // 表示是文件流,唤起浏览器下载,一般设置了这个,就要设置文件名
c.Header("Content-Disposition", "attachment; filename="+"牛逼.png") // 用来指定下载下来的文件名
c.Header("Content-Transfer-Encoding", "binary")   // 表示传输过程中的编码形式,乱码问题可能就是因为它
c.File("uploads/12.png")

完整代码:

func main() {router := gin.Default()router.GET("/download", func(c *gin.Context) {c.Header("Content-Type", "application/octet-stream")c.Header("Content-Disposition", "attachment; filename="+"牛逼.txt")c.File("思考一个问题的四连问.txt")})router.Run(":8000")
}

这样再使用游览器,就直接下载了!!

2.2 前后端模式下的文件下载

如果是前后端模式下,后端就只需要响应一个文件数据

文件名和其他信息就写在请求头中

c.Header("fileName", "xxx.png")
c.Header("msg", "文件下载成功")
c.File("uploads/12.png")

前端写法

async downloadFile(row) {this.$http({method: 'post',url: 'file/upload',data:postData,responseType: "blob"}).then(res => {const _res = res.datalet blob = new Blob([_res], {type: 'application/png'});let downloadElement = document.createElement("a");let href = window.URL.createObjectURL(blob); //创建下载的链接downloadElement.href = href;downloadElement.download = res.headers["fileName"]; //下载后文件名document.body.appendChild(downloadElement);downloadElement.click(); //点击下载document.body.removeChild(downloadElement); //下载完成移除元素window.URL.revokeObjectURL(href); //释放掉blob对象})}

2.3 中文乱码问题

前后端模式下的文件下载,进程会出现中文乱码问题,我们需要进行修改,并且指定一些格式

后端

func Download(c *gin.Context) {filename := url.QueryEscape("国家机密.txt")// 可唤起浏览器下载c.Header("Content-Disposition", "attachment; filename*=utf-8''"+filename) //c.Header("fileName", filename)c.File("uploads/国家机密.txt")
}

前端

async download() {let res = await axios.get("/download", {headers: {responseType: "blob"}})if (res.status === 200) {let binaryData = [];binaryData.push(res.data);let url = window.URL.createObjectURL(new Blob(binaryData)); //表示一个指定的file对象或Blob对象let a = document.createElement("a");document.body.appendChild(a);// 转码文件的标题let filename = decodeURI(res.headers.filename)// 调起文件下载a.href = url;a.download = filename; //命名下载名称a.click(); //点击触发下载window.URL.revokeObjectURL(url);}
}

这就是简单的文件上传和下载啦~~

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

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

相关文章

lesson2(补充)关于>>运算符和<<运算符重载

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 前言&#xff1a; cout和cin我们在使用时需要包含iostream头文件&#xff0c;我们可以知道的是cout是写在ostream类里的&#xff0c;cin是写在istream类里的&#xff0c;他们都是定义出的对象&#xff0c;而<< 和 >…

M1安装OpenPLC Editor

下载OpenPLC Editor for macOS.zip文件后&#xff0c;使用tar -zvxf命令解压&#xff0c;然后将"OpenPLC Editor"拖入到"应用程序"文件夹 右键点击"OpenPLC Editor"&#xff0c;打开这个""文件&#xff0c;替换为以下内容 #!/bin/bash…

香港服务器如何做负载均衡?

​  在现代互联网时代&#xff0c;随着网站访问量的不断增加&#xff0c;服务器的负载也越来越重。为了提高网站的性能和可用性&#xff0c;负载均衡成为了一种常见的解决方案。 什么是负载均衡? 负载均衡是一种技术解决方案&#xff0c;用于在多个服务器之间分配负载&#…

搜维尔科技:【应用】配备MTi-3的轻便型ROV,在水下进行地理标记视觉检测

部署潜水员进行水下摄像&#xff0c;不仅难度高而且费用昂贵&#xff0c;需要受过潜水和摄像两方面培训的专业人员来进行。但有些水下作业任务例如拍摄海底管道内部的照片&#xff0c;由于人员无法进入或危险度高的原因&#xff0c;无法由潜水员完成。 如今&#xff0c;俄罗…

vue源码分析(五)——vue render 函数的使用

文章目录 前言一、render函数1、render函数是什么&#xff1f; 二、render 源码分析1.执行initRender方法2.vm._c 和 vm.$createElement 调用 createElement 方法详解&#xff08;1&#xff09;区别&#xff08;2&#xff09;代码 3、原型上的_render方法&#xff08;1&#xf…

JWT详解解读读

&#x1f4d1;前言 本文主要是jwt解读文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是青衿&#x1f947; ☁️博客首页&#xff1a;CSDN主页放风讲故事 &#x1f304;每日一句&#xff1a;努力一点&#…

数据结构-初识泛型

写在前&#xff1a; 这一篇博客主要来初步的记录以下泛型的相关内容&#xff0c;内容比较琐碎&#xff0c;就不进行目录的整合&#xff0c;后续可能会对泛型这里进行系统性的梳理&#xff0c;此篇博客主要是对泛型有一个简单的认识与理解&#xff0c;需要知晓的内容。 当我调用…

七层负载均衡 HAproxy

一、HAproxy 1、负载均衡类型&#xff1a; (1) 无负载均衡&#xff1a; 没有负载均衡&#xff0c;用户直接连接到 Web 服务器。当许多用户同时访问服务器时&#xff0c;可能无法连接。 (2) 四层负载均衡&#xff1a; 用户访问负载均衡器&#xff0c;负载均衡器将用户的请求…

听GPT 讲Rust源代码--library/std(8)

题图来自Why is Rust programming language so popular?[1] File: rust/library/std/src/sys/sgx/abi/reloc.rs 在Rust源代码中&#xff0c;sgx/abi/reloc.rs文件的作用是定义了针对Intel Software Guard Extensions (SGX)的重定位相关结构和函数。 该文件中的Rela 结构定义了…

java之输入与输出的详细介绍

文章目录 输出的相关格式使用 Scanner 类进行控制台输入步骤&#xff1a;示例&#xff1a; 如何格式化输出&#xff1f;1. 使用 System.out.printf2. 使用 String.format printf与println 的区别printfprintln主要区别&#xff1a; 输出的相关格式 控制台输入是指通过命令行或…

C++ Qt/VTK装配体组成联动连接杆

效果 关键代码 #include "View3D.h" #include "Axis.h"#include <vtkActor.h> #include <vtkAppendPolyData.h > #include <vtkAreaPicker.h> #include <vtkAxesActor.h> #include <vtkBox.h> #include <vtkCamera.h>…

开源3D激光(视觉)SLAM算法汇总(持续更新)

原文连接 目录 一、Cartographer 二、hdl_graph_slam 三、LOAM 四、LeGO-LOAM 五、LIO-SAM 六、S-LOAM 七、M-LOAM 八、livox-loam 九、Livox-Mapping 十、LIO-Livox 十一、FAST-LIO2 十二、LVI-SAM 十三、FAST-Livo 十四、R3LIVE 十五、ImMesh 十六、Point-LIO 一、Cartograph…

辅助驾驶功能开发-功能规范篇(22)-3-L2级辅助驾驶方案功能规范

1.3.3 TLA系统功能定义 1.3.3.1 状态机 1.3.3.2 状态迁移图 1.3.3.3 功能定义 1.3.3.3.1 信号需求列表 1.3.3.3.2 系统开启关闭 1)初始化 车辆上电后,交通灯辅助系统(TLA)进行初始化,控制器需在 220ms 内发出第一帧报文,并在 3s 内完成内部自检,同时上电 3s 内不进行…

VR数字党建:红色文化展厅和爱国主义教育线上线下联动

伴随着党建思想的加深&#xff0c;很多政府单位都有打造VR党建展厅的想法&#xff0c;而党建基地也是激发爱国热情、凝聚人民力量、培养民族精神的重要场所。现如今&#xff0c;伴随着5G、VR等技术的成熟&#xff0c;VR数字党建积极推动运用VR技术&#xff0c;推动红色文化展厅…

PyTorch中grid_sample的使用方法

官方文档首先Pytorch中grid_sample函数的接口声明如下&#xff1a; torch.nn.functional.grid_sample(input, grid, modebilinear, padding_modezeros, align_cornersNone)input : 输入tensor&#xff0c; shape为 [N, C, H_in, W_in]grid: 一个field flow&#xff0c; shape为…

美颜SDK集成指南:为应用添加视频美颜功能

随着社交媒体和直播应用的兴起&#xff0c;视频美颜功能已成为用户追求的一项热门特性。用户希望能够在拍摄照片或进行实时视频直播时&#xff0c;使用美颜功能来增强其外观。为了满足这一需求&#xff0c;开发者可以考虑集成美颜SDK&#xff0c;为其应用增加这一吸引人的功能。…

Qt实现卡牌对对碰游戏

效果 闲来无事&#xff0c;实现一个对对碰游戏&#xff0c;卡牌样式是火影动漫。 先上效果&#xff1a; 卡牌对对碰_火影主题 玩法 启动游戏&#xff0c;进入第一关卡&#xff0c;所有卡牌都为未翻开状态&#xff0c;即背面朝上&#xff1b;点击卡牌&#xff0c;则将卡牌翻开…

常用排序算法

目录 直接插入排序 希尔排序 ​编辑 选择排序 堆排序 冒泡排序 快速排序 hoare版 挖坑法 前后指针法 非递归 归并排序 非递归 计数排序 直接插入排序 直接插入排序跟依次模扑克牌一样&#xff0c;将最后一张牌依次与前面的牌比较&#xff0c;最后将牌插入到指定位…

Python深度学习实战-基于tensorflow原生代码搭建BP神经网络实现分类任务(附源码和实现效果)

实现功能 前面两篇文章分别介绍了两种搭建神经网络模型的方法&#xff0c;一种是基于tensorflow的keras框架&#xff0c;另一种是继承父类自定义class类&#xff0c;本篇文章将编写原生代码搭建BP神经网络。 实现代码 import tensorflow as tf from sklearn.datasets import…

【数据库】

文章目录 1. 聚合函数练习&#xff1a; 2. 子查询 1. 聚合函数 where中过滤条件中不能写聚合函数&#xff0c;有聚合函数需要写到Having中 方式一效率高&#xff1a; Select执行流程 练习&#xff1a; 2. 第七题&#xff1a;count(*)有问题&#xff0c;原因是左外连接后…