Gin框架集成了本地、阿里云存储、腾讯云、七牛云文件存储方式,并留有继续拓展其他云存储能力,本文介绍多种文件存储使用和继续集成其他云存储方法指导

简介: Go语言web框架Gin集成阿里云存储等多文件存储方式,统一调用与后台管理,切换便捷,提升开发效率。

前言

基于gin-web框架开发GoFly快速开发框架v3.01版本已更新,本次更新最大亮点是把多种文件存储方式集成在框架中,放弃之前单一种方式做成独立插件安装,单个插件虽然有代码少的优点,但是在实际业务开发时,当切换其他存储位置时,之前存储位置文件无法访问,且代码结构相对零散。所以从实现业务需求出发,我们决定把多种存储方式集成在一起,统一代码结构,统一调用,后台统一管理,切换方便。

在软件开发中文件上传存储、访问文件是一个必不可少的功能,好用文件存储管理可让开发省去很多的时间,这也是GoFly框架本次更新重视文件文件存储管理的原因。

如下图GoFly后台的文件存储配置,开发时可以直接通过后台配置不同存储位置参数,点“文件存储方式”切换并提交“保存”即可完成不同文件存储位置变更。

ali_2025-11-18_080157_576.png

在线体验地址:https://spl.goflys.cn/webbusiness/ ,账号:gofly   密码:gofly123

开发使用方法

框架把多种文件存储位置集成后,提供给业务开发统一调用函数,只需在后台选择存储位置和配置相关参数即可,代码部分就不用单独处理。

统一文件处理模块引入:

import (
  "gofly/utils/extend/uploads"
)

image.gif

1.统一上传文件函数

函数名:UploadFile

参数:c请求上下文,file上传文件流

返回:url是返回文件路径

//处理文件上传,bin返回地址
url, cover_url, err := uploads.New().UploadFile(c, file)

image.gif

注意:如果在选择文件上传云服务器,但某个功能文件需要单独本地存储,则New()添加参数如下:

//处理文件上传,bin返回地址
url, cover_url, err := uploads.New("local").UploadFile(c, file)
if err != nil {
  gf.Failed().SetMsg("上传文件失败").SetData(err).Regin(c)
  return
}

image.gif

其中New("local")参数local可以改为:alioss、tencentcos、qiniuoss等其他云存储名。

2.统一删除文件函数

函数名:DelFile

参数:url是删除文件路径,不包含域名的路径。

err:=uploads.DelFile(url)

image.gif

3.示例代码

实际调用上传函数实例代码:

// 上传文件
func (api *Upfile) LocalFile(c *gf.GinCtx) {
  //file文件流
  file, err := c.FormFile("file")
  if err != nil {
    gf.Failed().SetMsg("获取数据失败").SetData(err).Regin(c)
    return
  }
  //判断文件是否已经传过
  fileContent, _ := file.Open()
  defer fileContent.Close()
  var byteContainer []byte = make([]byte, 1000000)
  fileContent.Read(byteContainer)
  m_d5 := md5.New()
  m_d5.Write(byteContainer)
  sha1_str := hex.EncodeToString(m_d5.Sum(nil))
  //查找该用户是否传过
  attachment, _ := gf.Model("business_attachment").Where("business_id", businessID).
    Where("sha1", sha1_str).Fields("id,pid,name,title,type,url,filesize,mimetype,cover_url as cover").Find()
  if attachment != nil { //文件是否已经存在
    //更新到最前面
    maxId, _ := gf.Model("business_attachment").Where("business_id", businessID).Order("weigh desc").Value("id")
    if maxId != nil {
      gf.Model("business_attachment").Data(map[string]interface{}{"weigh": maxId.Int() + 1, "pid": 1}).Where("id", attachment["id"]).Update()
    }
    gf.Success().SetMsg("文件已上传").SetData(attachment).Regin(c)
  } else {
    //这里处理文件上传 并返回地址, uploads.New().UploadFile就是把文件上传到配置设定位置
    url, cover_url, err := uploads.New().UploadFile(c, file)
    if err != nil {
      gf.Failed().SetMsg("上传文件失败").SetData(err).Regin(c)
      return
    }
    filename_arr := strings.Split(file.Filename, ".")
    //文件类型
    fileData := gf.Map{
      "type":        0, //图片
      "pid":         1, //存储在默认文件夹
      "sha1":        sha1_str,
      "title":       filename_arr[0],
      "name":        file.Filename,
      "url":         url,       //附件路径
      "cover_url":   cover_url, //封面
      "storage":     "local",
      "createtime":  time.Now().Unix(),
      "filesize":    file.Size,
      "mimetype":    file.Header["Content-Type"][0],
    }
    //保存数据
    file_id, _ := gf.Model("business_attachment").Data(fileData).InsertAndGetId()
    //更新排序
    gf.Model("business_attachment").Data(map[string]interface{}{"weigh": file_id}).Where("id", file_id).Update()
    //处理预览url地址
    gf.Success().SetMsg("文件上传成功").SetData(gf.GetFullUrl(url)).Regin(c)
  }
}

image.gif

如果某个功能需单独存储在指定位置,和系统设置的全局存储位置不同,比如把使用频率或者访问速度要求较低的,我们可以把他存储在本地,那么把uploads.New("local").UploadFile(c, file)的New函数中添加存储位置名,本地存储名为:local 则上传本地调用的代码如下:

//处理文件上传,并返回地址
url, cover_url, err := uploads.New("local").UploadFile(c, file)
if err != nil {
  gf.Failed().SetMsg("上传文件失败").SetData(err).Regin(c)
  return
}

image.gif

4.框架封装好的上传文件接口

框架已经为各端客户端封装好了,可以直接调用上传文件接口,使用GoFly框架开发时没有特殊要求就不需要写上传文件接口代码,直接调用现成就实现上传。

4.1管理后后台(admin端)

接口:域名+admin/datacenter/upfile/upload

4.2管理后后台(business端)

接口:域名+business/datacenter/upfile/upload

4.3 非管理后台客户端(微信小程序、app、h5应用)

接口:域名+common/upload/upfile

Gin集成阿里云OSS对象存储指导

如果你想了解如何集成阿里云存储,现在到项目打开路径:utils\extend\uploads,在uploads目录下有个index.go是统一调用函数入口及配置存储代码。目录下的local.go为本地上传功能代码、aliOSS.go为阿里云存储功能代码等云存储功能代码。下面介绍阿里云存储集成步骤:

1.创建存储代码文件

在utils\extend\uploads创建一个名为:aliOSS.go 代码框架如下:

package uploads

import (
    "errors"
    "fmt"
    "gofly/utils/gf"
    "mime/multipart"
    "path"
    "path/filepath"
    "time"

    "github.com/aliyun/aliyun-oss-go-sdk/oss"
)

// 阿里云 OSS 文档
// https://help.aliyun.com/zh/oss/developer-reference/introduction-3?spm=5176.8466032.console-base_help.dexternal.67181450WWM1Nx

type AliOSS struct {
    Client *oss.Client
    Ready  bool
    Config Config
    Bucket *oss.Bucket
}

func (m *AliOSS) InitClient(config Config) {
    m.Ready = false
    m.Config = config
    client, err := oss.New(config.Endpoint, config.KeyId, config.Secret)
    if err != nil {
        return
    }
    m.Client = client
    m.Bucket, err = client.Bucket(config.BucketName)
    if err != nil {
        return
    }
    m.Ready = true
}

// 上传文件
func (m *AliOSS) UploadFile(c *gf.GinCtx, file *multipart.FileHeader) (url, cover_url string, err error) {
    if !m.Ready {
        err = errors.New("not ready")
        return
    }
    fd, err := file.Open()
    if err != nil {
        return
    }
    defer fd.Close()
    //注意:文件名称必须以alioss开头,MakeFileName函数就是生成以alioss开头的文件名称
    path_name := fmt.Sprintf("%v/%v/%v", m.Config.DirPath, time.Now().Format("20060102"), MakeFileName(file, "alioss"))
    url = path_name
    err = m.Bucket.PutObject(path_name, fd)
    return
}

// 删除文件(单个)
func (m *AliOSS) RemoveFile(fileUrl string) error {
    if !m.Ready {
        return errors.New("not ready")
    }
    return m.Bucket.DeleteObject(fileUrl)
}

// 下载文件
func (m *AliOSS) DownloadFile(fileUrl string) error {
    fileUrl, cloudFileUrl := InitFileUrl(fileUrl, m.Config)
    if !m.Ready {
        return errors.New("not ready")
    }
    // 检查对象是否存在
    _, err := m.Bucket.GetObjectMeta(cloudFileUrl)
    if err != nil {
        return err
    }
    // 下载文件
    return m.Bucket.GetObjectToFile(cloudFileUrl, fileUrl)
}

// 移动文件
func (m *AliOSS) MoveFile(fileUrl string, targerDir string) (string, error) {

    // 本地移动
    fileUrl, _ = InitFileUrl(fileUrl, m.Config)
    targerUrl := path.Join(targerDir, filepath.Base(fileUrl))
    targerUrl, _ = InitFileUrl(targerUrl, m.Config)
    MoveFile(fileUrl, targerUrl)

    // 阿里云移动
    // 01. 拷贝
    _, fileUrl = InitFileUrl(fileUrl, m.Config)
    _, targerUrl = InitFileUrl(targerUrl, m.Config)
    _, err := m.Bucket.CopyObject(fileUrl, targerUrl)
    if err != nil {
        return "", err
    }
    // 02. 删除
    err = m.Bucket.DeleteObject(fileUrl)
    if err != nil {
        return "", err
    }
    return targerUrl, nil
}

image.gif

2.在index.go引入阿里云存储功能

写好上传、删除等相关接口后,需要把aliOSS.go在统一调用index.go文件注册,具体如下

2.1在New初始配置函数中添加


// 初始配置,如果传uptype(上传方式),则直接示例传入上传方式,不传则从配置文件获取设置的上传方式
func New(uptype ...string) StaticCloud {
    var staticCloud StaticCloud
    var upTypeStr string = ""
    var config = Config{}
    if len(uptype) > 0 && uptype[0] != "" {
        upTypeStr = uptype[0]
    } else {
        confType, _ := gcfg.Instance("upload").Get(ctx, "Type")
        upTypeStr = confType.String()
    }
    switch upTypeStr {
    case "alioss":
        alioss, _ := gcfg.Instance("upload").Get(ctx, "alioss")
        mapConf := alioss.Map()
        config = Config{
            BaseUrl:    gf.String(mapConf["ABaseUrl"]),
            Endpoint:   gf.String(mapConf["AEndpoint"]),
            KeyId:      gf.String(mapConf["AKeyId"]),
            Secret:     gf.String(mapConf["ASecret"]),
            BucketName: gf.String(mapConf["ABucketName"]),
            DirPath:    gf.String(mapConf["ADirPath"]),
        }
        staticCloud = &AliOSS{}
    case "tencentcos":
        tencentcos, _ := gcfg.Instance("upload").Get(ctx, "tencentcos")
        mapConf := tencentcos.Map()
        config = Config{
            BaseUrl:    gf.String(mapConf["TBaseUrl"]),
            Endpoint:   gf.String(mapConf["TEndpoint"]),
            KeyId:      gf.String(mapConf["TKeyId"]),
            Secret:     gf.String(mapConf["TSecret"]),
            BucketName: gf.String(mapConf["TBucketName"]),
            Region:     gf.String(mapConf["TRegion"]),
            DirPath:    gf.String(mapConf["TDirPath"]),
        }
        staticCloud = &TencentCOS{}
    case "qiniuoss":
        qiniuoss, _ := gcfg.Instance("upload").Get(ctx, "qiniuoss")
        mapConf := qiniuoss.Map()
        config = Config{
            BaseUrl:    gf.String(mapConf["QBaseUrl"]),
            Endpoint:   gf.String(mapConf["QEndpoint"]),
            KeyId:      gf.String(mapConf["QKeyId"]),
            Secret:     gf.String(mapConf["QSecret"]),
            BucketName: gf.String(mapConf["QBucketName"]),
            DirPath:    gf.String(mapConf["QDirPath"]),
            UseHTTPS:   gf.Bool(mapConf["QUseHTTPS"]),
            Zone:       gf.Int(mapConf["QZone"]),
        }
        staticCloud = &QiniuOSS{}
    default:
        local, _ := gcfg.Instance("upload").Get(ctx, "local")
        mapConf := local.Map()
        config = Config{
            BaseUrl: gf.String(mapConf["LBaseUrl"]),
            DirPath: gf.String(mapConf["LDirPath"]),
        }
        staticCloud = &Local{}
    }
    staticCloud.InitClient(config)
    return staticCloud
}

image.gif

2.2配置统一删除

// 删除附件统一入口,结果返回:bool
func DelFile(fileUrl string) error {
    //处理地址
    filseName := gfile.Name(fileUrl)
    uptype := ""
    if strings.HasPrefix(filseName, "local") { //本地存储
        uptype = "local"
    } else if strings.HasPrefix(filseName, "alioss") { //阿里云
        uptype = "alioss"
    } else if strings.HasPrefix(filseName, "tencentcos") { //腾讯云
        uptype = "tencentcos"
    } else if strings.HasPrefix(filseName, "qiniuoss") { //七牛云
        uptype = "qiniuoss"
    } else { //默认返回设置上传方式的地址
        UpType, _ := gcfg.Instance("upload").Get(ctx, "Type")
        uptype = UpType.String()
    }
    return New(uptype).RemoveFile(fileUrl)
}

image.gif

3.添加配置文件

在后端资源目录:resource\config\upload.yaml添加阿里云存储配置参数:

# 存储方式
Type: local
# 配置传输文件最大值,如上传文件最大上限,单位为MB
MaxBodySize: 600
# 允许上传的文件类型
AllowedExt: .jpg,.jpeg,.png,.pdf,.ico
# 本地存储配置
local: 
  LBaseUrl: http://localhost:8200
  LDirPath: /resource/uploads/
# 阿里云静态云存储配置
alioss:
  ABaseUrl: https://hcoder.oss-cn-beijing.aliyuncs.com/
  AEndpoint: oss-cn-beijing.aliyuncs.com
  AKeyId: 
  ASecret: 
  ABucketName: 
  ADirPath: 
# 腾讯云静态云存储配置
tencentcos:
  TBaseUrl: https://gofly-1257246782.cos.ap-nanjing.myqcloud.com
  TEndpoint: 
  TKeyId: AKIDGUYaP1TmtpY4NSJxlWK0eAbzEKEvRkw0
  TSecret: 
  TBucketName: gofly-1257246782
  TRegion: ap-nanjing
  TDirPath: /goflys
# 七牛云存储配置
qiniuoss:
  QBaseUrl: http://t3wcppubp.hn-bkt.clouddn.com/
  QEndpoint: 
  QKeyId: dtxSwoGm1hwkn5FvhEI8QBvIKxn08_5iYypjC4u8
  QSecret: 
  QBucketName: goflys
  QDirPath: image
  QDestBucketName: <nil>
  QUseHTTPS: false
  QZone: 4

image.gif

4.把新增存储方式添加管理后台

后端添加好后,需要把新增加存储方式添加到管理后台,方便配置和管理。在管理后台前端代码位置:src\views\datacenter\configuration\components\UploadConfig.vue添加代码:

在js代码中handleChangeType函数条件阿里云的数据配置,代码如下

//切换上传方式
    const handleChangeType=(value:any)=>{
      if(value=="local"){
        formData.value=Object.assign({},formData.value,{BaseUrl:baseData.local.LBaseUrl,DirPath:baseData.local.LDirPath})
      }else if(value=="tencentcos"){
        formData.value=Object.assign({},formData.value,{BaseUrl:baseData.tencentcos.TBaseUrl,Endpoint:baseData.tencentcos.TEndpoint,
          KeyId:baseData.tencentcos.TKeyId,Secret:baseData.tencentcos.TSecret,BucketName:baseData.tencentcos.TBucketName,
          Region:baseData.tencentcos.TRegion,DirPath:baseData.tencentcos.TDirPath})
      }else if(value=="alioss"){
        formData.value=Object.assign({},formData.value,{BaseUrl:baseData.alioss.ABaseUrl,Endpoint:baseData.alioss.AEndpoint,
          KeyId:baseData.alioss.AKeyId,Secret:baseData.alioss.ASecret,BucketName:baseData.alioss.ABucketName,
          DirPath:baseData.alioss.ADirPath})
      }else if(value=="qiniuoss"){
        formData.value=Object.assign({},formData.value,{BaseUrl:baseData.qiniuoss.QBaseUrl,Endpoint:baseData.qiniuoss.QEndpoint,
          KeyId:baseData.qiniuoss.QKeyId,Secret:baseData.qiniuoss.QSecret,BucketName:baseData.qiniuoss.QBucketName,
        DestBucketName:baseData.qiniuoss.QDestBucketName,UseHTTPS:baseData.qiniuoss.QUseHTTPS,Zone:baseData.qiniuoss.QZone,
        DirPath:baseData.qiniuoss.QDirPath})
      }
      console.log(formData.value)
    }

image.gif

到此我们就把阿里云存储介绍完了,大家可以通过本文介绍了解,Gin集成的GoFly框架文件存储使用和继续扩展新存储方式的方法。

相关文章
|
6月前
|
JSON 自然语言处理 搜索推荐
银行卡归属地及开户行查询API查询实战指南
银行卡归属地及开户行查询API,通过卡号快速识别发卡行、开户地及卡种信息,支持全国1500+银行,数据实时更新。提供结构化数据返回,广泛应用于支付、风控、用户画像等场景,助力金融系统高效、安全运行。
1861 7
|
6月前
|
存储 监控 调度
如何在阿里云OSS之间进行数据迁移呢?
讲解如何在阿里云对象存储OSS之间进行跨账号、跨地域、以及同地域内的数据迁移,包括数据迁移之前的准备工作和实施数据迁移以及一些后续操作,使用在线迁移服务,您可以将第三方数据轻松迁移至阿里云对象存储OSS,也可以在对象存储OSS之间进行灵活的数据迁移。
|
4天前
|
人工智能 安全 应用服务中间件
首个 Clawdbot 全流程部署方案!真“AI 个人助理”来了!
GitHub爆火AI Agent Moltbot(原Clawdbot)上线即获7.6万+ Star!它能理解自然语言、调用工具、自动执行任务。阿里云轻量应用服务器推出“开箱即用”部署方案:预装环境、直连百炼大模型、支持钉钉等消息通道,5分钟一键启用,稳定、安全、低成本。
首个 Clawdbot 全流程部署方案!真“AI 个人助理”来了!
|
6月前
|
存储 人工智能 缓存
如何创建、修改和删除OSS加速器?
OSS加速器通过将热点数据缓存至高性能存储,提升数据访问速度,适用于AI、大数据分析等高并发场景。本文介绍其创建、删除及容量调整操作,助力优化业务性能。
|
6月前
|
缓存 安全 编译器
C++面试周刊(3):面试不慌,这样回答指针与引用,青铜秒变王者
《C++面试冲刺周刊》第三期聚焦指针与引用的区别,从青铜到王者级别面试回答解析,助你21天系统备战,直击高频考点,提升实战能力,轻松应对大厂C++面试。
547 132
C++面试周刊(3):面试不慌,这样回答指针与引用,青铜秒变王者
|
6月前
|
存储 缓存 网络协议
如何使用CDN加速访问OSS存储的图片资源?
通过阿里云CDN加速OSS上的图片和视频资源,可显著提升访问速度、降低带宽成本。CDN将静态资源缓存至离用户最近的节点,减少加载时间,并提供图像处理、缓存优化等功能,提升用户体验。同时,CDN还支持访问数据分析,助力运营决策。本文详解如何通过CDN控制台配置OSS加速,包括添加域名、设置CNAME、配置缓存策略等步骤,帮助您快速实现资源加速。
|
6月前
|
编解码 数据处理 API
如何用阿里云OSS对图片和视频进行数据处理?
本文介绍了如何利用阿里云对象存储OSS进行图片和视频处理。OSS提供了丰富的功能,如图片的缩放、裁剪、旋转和水印添加等,用户只需在图片URL后附加处理参数即可实现自动化处理。同时,OSS还支持自定义样式模板,便于批量操作。对于视频处理,OSS支持转码、截图、拼接等功能,满足多终端播放需求。通过OSS的API和SDK,开发者可以方便地集成这些功能,提升数据管理效率。
|
7月前
|
物联网 Linux 开发者
快速部署自己私有MQTT-Broker-下载安装到运行不到一分钟,快速简单且易于集成到自己项目中
本文给物联网开发的朋友推荐的是GMQT,让物联网开发者快速拥有合适自己的MQTT-Broker,本文从下载程序到安装部署手把手教大家安装用上私有化MQTT服务器。
1785 5
|
4月前
|
缓存 边缘计算 运维
基于 Cloudflare Workers 构建高性能知识库镜像服务:反向代理与 HTML 动态重写实践
基于Cloudflare Workers构建的边缘计算镜像服务,通过反向代理、HTML动态重写与智能缓存,优化维基百科等知识平台的访问性能。支持路径映射、安全头清理与容错回退,实现免运维、低延迟、高可用的Web加速方案,适用于教育、科研等合规场景。
939 8
|
6月前
|
存储 缓存 固态存储
什么是OSS加速器?
OSS加速器通过将热点数据缓存至高性能NVMe SSD,提供低延迟、高QPS的数据访问服务,适用于AI模型推理、大数据分析等场景,支持弹性伸缩和多种预热策略,提升数据访问效率。