基于gin框架的文件上传(逐行解析)

news2024/11/15 1:45:16
            基于gin框架的文件上传(逐行解析)

记录一下使用gin框架完成一个文件上传的功能,一下是实现该功能的代码,适合小白,代码都有逐行解释!

app.go:

package router

import (
	"chat/service"
	"github.com/gin-gonic/gin"
)

func Router() *gin.Engine {
	r := gin.Default()
	//上传文件,使用post请求
	r.POST("/attach/upload", service.Upload)
	return r
}

attach.go:

package service

import (
	"chat/utils"
	"fmt"
	"github.com/gin-gonic/gin"
	"io"
	"math/rand"
	"net/http"
	"os"
	"strings"
	"time"
)

func Upload(c *gin.Context) {
	UploadLocal(c)
}

// 上传文件到本地
func UploadLocal(c *gin.Context) {
	w := c.Writer //获取响应的gin上下文写入器
	req := c.Request//获取当前请求对象
	//从请求中通过FormFile方方法获取指定名称("file")的文件
	//srcFile为获取到的源文件
	//head为文件的头部信息
	//err为可能出现的错误
	srcFile, head, err := req.FormFile("file") 
	if err != nil {
		//使用utils.RespFail()函数响应写入失败信息和错误内容
		utils.RespFail(w, err.Error())
	}
//定义默认的文件后缀为".png"
	suffix := ".png"
	//从head中获取文件信息head有以下常用变量
	//head.Header 文件的头部信息,包含一些与文件相关的元数据,比如文件的类型、大小
	//head.Size 文件的大小
	//head.Filename 文件的名字
	ofilName := head.Filename 
	//定义一个字符串切片tem,使用strings。Split()将文件名ofilName按照(.)进行分割再装入这个切片当中,
	tem := strings.Split(ofilName, ".")
	//如果分割后的结果长度大于1,表示有后缀
	if len(tem) > 1 {
		// 将后缀更新为分割后的最后一部分(该切片的最后一个元素)
		suffix = "." + tem[len(tem)-1]
	}
	// 根据当前时间的 Unix 时间戳、随机生成的 32 位整数和后缀生成文件名
	fileName := fmt.Sprintf("%d%04d%s", time.Now().Unix(), rand.Int31(), suffix)
	//使用os.Create()在指定路径("./files/"+fileName)创建新的文件
	dstFile, err := os.Create("./files/" + fileName)
	if err != nil {
		//使用utils.RespFail()函数响应写入失败信息和错误内容
		utils.RespFail(w, err.Error())
	}
	// 使用 io.Copy 方法将源文件的内容拷贝到目标文件中
	// err 为可能出现的拷贝过程中的错误
	_, err = io.Copy(dstFile, srcFile)
	if err != nil {
		//使用utils.RespFail()函数响应写入失败信息和错误内容
		utils.RespFail(w, err.Error())
	}
	//构建文件的完整的URL
	url := "./files/" + fileName
	// 使用 utils.RespOK 函数向响应写入成功信息、文件的 URL 以及成功消息
	utils.RespOK(w, url, "发送成功")
}

resp.go:主要用处理请求响应的各种状态

package utils

import (
    // 导入相关包
    "encoding/json"
    "fmt"
    "net/http"
)

type H struct {
    // 定义结构体 H,包含代码、消息、数据、行数和总数等字段
    Code  int
    Msg   string
    Data  interface{}
    Rows  interface{}
    Total interface{}
}

// Resp 函数,用于响应数据
func Resp(w http.ResponseWriter, code int, data interface{}, msg string) {
    // 设置响应头的内容类型为 JSON
    w.Header().Set("Content-Type", "application/json")
    // 设置响应状态码为 200(OK)
    w.WriteHeader(http.StatusOK)
    h := H{
        // 初始化结构体 H 的字段
        Code: code,
        Data: data,
        Msg:  msg,
    }
    // 对结构体 H 进行 JSON 序列化操作
    ret, err := json.Marshal(h)
    if err!= nil {
        // 处理序列化错误
        fmt.Println(err)
    }
    w.Write(ret)
}

// RespList 函数,用于响应列表数据
func RespList(w http.ResponseWriter, code int, data interface{}, total interface{}) {
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusOK)
    h := H{
        // 初始化结构体 H 的字段
        Code:  code,
        Rows:  data,
        Total: total,
    }
    ret, err := json.Marshal(h)
    if err!= nil {
        // 处理序列化错误
        fmt.Println(err)
    }
    w.Write(ret)
}

// RespFail 函数,用于响应失败信息
func RespFail(w http.ResponseWriter, msg string) {
    // 调用 Resp 函数,设置代码为-1,表示失败
    Resp(w, -1, nil, msg)
}

// RespOK 函数,用于响应成功信息
func RespOK(w http.ResponseWriter, data interface{}, msg string) {
    // 调用 Resp 函数,设置代码为 0,表示成功
    Resp(w, 0, data, msg)
}

// RespOKList 函数,用于响应成功的列表信息
func RespOKList(w http.ResponseWriter, data interface{}, total int) {
    // 调用 RespList 函数,设置代码为 0,表示成功
    RespList(w, 0, data, total)
}

main.go:

package main

import "chat/router"

func main() {
	r := router.Router()
	r.Run(":8081")
}

写完了:测试一下

使用postman提交一个文件参数

在这里插入图片描述

查看是否上传成功

在这里插入图片描述

可以看到文件上传成功了!

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

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

相关文章

【matlab】matlab实现倒谱法基音频率检测和共振峰检测(源码+音频文件)【独一无二】

👉博__主👈:米码收割机 👉技__能👈:C/Python语言 👉公众号👈:测试开发自动化【获取源码商业合作】 👉荣__誉👈:阿里云博客专家博主、5…

校园卡没到期可以换套餐吗

校园卡没到期可以换套餐吗 校园卡是可以更换套餐的,但具体问题还是要具体分析,根据实际情况来进行选择。 校园卡改套餐分为两种情况,一种是没有签订任何协议的校园卡套餐,这种情况用户是可以随时更换通信资费套餐的;另…

【PHP【实战版】系统性学习】——登录注册页面的教程,让编写PHP注册变成一个简单的事情

👨‍💻个人主页:开发者-曼亿点 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 曼亿点 原创 👨‍💻 收录于专栏&#xff1a…

Oracle SQL优化案例-查询Null值走索引

网友发来一个SQL&#xff0c;说他们公司的一个SQL要优化帮忙看一下&#xff0c;执行计划如下&#xff1a; -------------------------------------SELECT * FROM (SELECT * FROM TXS C WHERE C.A ISNULL OR C.A ORDER BY ID_TXS DESC) WHERE ROWNUM<100​---------------…

集成平台建设方案(大数据中台技术方案)—Word原件

基础支撑平台主要承担系统总体架构与各个应用子系统的交互&#xff0c;第三方系统与总体架构的交互。需要满足内部业务在该平台的基础上&#xff0c;实现平台对于子系统的可扩展性。基于以上分析对基础支撑平台&#xff0c;提出了以下要求&#xff1a; 基于平台的基础架构&…

arm架构下安装conda

一、参考文章&#xff1a;感谢这位网友的分享&#xff0c;搬过来以备过几天使用&#xff0c;这种小众系统真的有些麻烦解决方案&#xff1a;ARM架构下安装Miniconda 离线配置Conda环境的全流程及踩坑避坑指南 - 技术栈 二、步骤 2.1 确认系统架构 uname -m 2.2 根据架构下载…

云贝教育 |【直播课】5月19日Oracle 19c OCM认证大师课 即将上课了!(附课件预览)

贝教育独家认证课OCM全网价格最低&#xff0c;性价比最高&#xff01;&#xff01;&#xff01; Oracle 19c OCM认证大师培训 - 课程体系 - 云贝教育 (yunbee.net) OCM部分课件预览 Oracle Database 19c Certified Master Exam (OCM) 认证大师 25 天 / 150课时 什么是Oracle 1…

浅析vue3自定义指令

vue3中可以像下面这样使用自定义指令。 这里我们只是定义了一个vFoucs变量&#xff0c;vue怎么知道这是一个指令呢&#xff1f; 这是因为约定大于配置&#xff0c;vue3中有这样一个约定&#xff08;截图来自官方文档&#xff09;&#xff1a; 注意这里说的是驼峰命令&#x…

插入法(直接/二分/希尔)

//稳定耗时&#xff1a; 双向冒泡&#xff0c;可指定最大最小值个数MaxMinNum<nsizeof(Arr)/sizeof(Arr[0]), void BiBubbleSort(int Arr[],int n&#xff0c;int MaxMinNum){int left0,rightn-1;int i;bool notDone true;int temp;int minPos;while(left<right&&am…

《Linux运维总结:ARM64架构CPU基于docker-compose一离线部署rabbitmq 3.10.25容器版镜像模式集群》

总结&#xff1a;整理不易&#xff0c;如果对你有帮助&#xff0c;可否点赞关注一下&#xff1f; 更多详细内容请参考&#xff1a;《Linux运维篇&#xff1a;Linux系统运维指南》 一、部署背景 由于业务系统的特殊性&#xff0c;我们需要面向不通的客户安装我们的业务系统&…

情感感知OCR:整合深度学习技术提升文字识别系统的情感理解能力

摘要&#xff1a;随着深度学习技术的发展&#xff0c;文字识别&#xff08;OCR&#xff09;系统在识别准确率和速度上取得了长足的进步。然而&#xff0c;在处理文本时&#xff0c;仅仅依靠字符和词语的识别并不足以满足用户对信息的全面理解需求。本文提出了一种新颖的方法&am…

Navicat 17:先睹为快

官方声明&#xff1a;Navicat 17&#xff08;英文版&#xff09;目前处于测试阶段中&#xff0c;并计划 5 月 13 日发布&#xff01; 如果你觉得 Navicat 16 已经推出很多令人兴奋的新功能&#xff0c;那么这次你可能要好好看看 Navicat 17&#xff0c;本次升级涵盖了更多的内容…

vscode切换分支及合并分支操作教程

工具&#xff1a;gitee、git 、vscode、Git Graph 点击可以看到分支管理明细。 一、前提 1、首先要有两个分支 &#xff08;1&#xff09;分支说明&#xff1a; test&#xff1a; 测试分支 feature/luo-20240508&#xff1a;自己的开发分支 &#xff08;2&#xff09;分支说…

【启明智显分享】国产自主HMI核心板Model3

Model3是一款高性能的工业级HMI&#xff08;人机界面&#xff09;核心板&#xff0c;也是一款纯国产HMI方案&#xff0c;工业级标准&#xff0c;稳定、可靠&#xff1b; 工业级HMI芯片–Model3 纯国产HMI方案 Model3核心板&#xff0c;具有2D加速&#xff0c;PNG解码&…

生产性服务业与生活性服务业如何区分

服务业的兴旺发达是现代经济的显著特征&#xff0c;是经济社会发展的必然趋势&#xff0c;是衡量经济发展现代化、国际化、高端化的重要标志。生产性服务业和生活性服务业是服务业的重要组成部分&#xff0c;是当前中国经济最具活力的产业&#xff0c;也是未来经济发展最具潜力…

【linux-IMX6ULL-定时器-GPT-串口配置流程-思路】

目录 1. 定时器配置流程1.1 EPIT定时器简介1.2 定时器1(epit1)的配置流程1.3 配置代码(寄存器版本)1.4 定时器-配合按键消抖1.4.1 实现原理1.4.2 代码实现&#xff08;寄存器版&#xff09; 2. GPT定时器实现高精度延时2.1 延时原理分析2.2 代码实现 3. UART串口配置流程3.1 UA…

SpringCloudAlibaba:4.2云原生网关higress的基本使用

概述 简介 Higress是基于阿里内部的Envoy Gateway实践沉淀、以开源Istio Envoy为核心构建的下一代云原生网关&#xff0c; 实现了流量网关 微服务网关 安全网关三合一的高集成能力&#xff0c;深度集成Dubbo、Nacos、Sentinel等微服务技术栈 定位 在虚拟化时期的微服务架构…

文本检测模型 DBNet 一种基于分割算法的模型 对每个像素点进行自适应二值化,并将二值化过程与网络训练相结合 可微分二值化模块 概率图

文本检测模型 DBNet DBNet文本检测模型是一种基于分割算法的模型,其优化之处在于对每个像素点进行自适应二值化,并将二值化过程与网络训练相结合。 传统的文本检测方法通常将二值化作为一个后处理步骤,与网络训练分开进行。而DBNet则提出了一种可微分的二值化方法,即将文…

类加载机制(双亲委派机制)

文章目录 JVM的作用是什么双亲委派机制加载流程 JVM的作用是什么 我们运行Java程序时&#xff0c;要安装JDK&#xff0c;JDK包含JVM&#xff0c;不同环境的JDK都是不同的。 Java 代码在编译后会形成 class 的字节码文件&#xff0c;该字节码文件通过 JVM 解释器&#xff0c;生…

【Linux】基于 Jenkins+shell 实现更新服务所需文件 -->两种方式:ssh/Ansible

&#x1f468;‍&#x1f393;博主简介 &#x1f3c5;云计算领域优质创作者   &#x1f3c5;华为云开发者社区专家博主   &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社区&#xff1a;运维交流社区 欢迎大家的加入&#xff01; &#x1f40b; 希望大家多多支…