工程实践-Go的文件上传与下载 | 青训营;

237 阅读4分钟

Go的文件上传与下载(Gin)

1.安装Gin

1.1 步骤

  1. 首先,确保你已经安装了Go编程语言。你可以从官方网站(golang.org/dl/)上下载并安装适合你操作系统的Go软件包。

  2. 打开终端或命令提示符,并执行以下命令来确认Go是否正确安装:

     go version
    
  3. 确认Go成功安装后,接下来要安装Gin。在终端或命令提示符中执行以下命令:

     go get -u github.com/gin-gonic/gin
    

    这个命令会自动从GitHub上下载Gin库,并将其安装在你的GOPATH目录中。

  4. 安装完成后,你可以在Go项目中导入Gin并开始使用。以下是一个简单的示例代码:

     package main
     ​
     import (
        "github.com/gin-gonic/gin"
     )
     ​
     func main() {
        // 创建一个Gin实例
        r := gin.Default()
     ​
        // 定义路由
        r.GET("/", func(c *gin.Context) {
           c.JSON(200, gin.H{
              "message": "Hello, Gin!",
           })
        })
     ​
        // 运行服务器
        r.Run()
     }
    

2.分层设计

image.png

2.1 规范

Gin是一个轻量级的Web框架,它没有固定的分层设置。但是,根据最佳实践,你可以根据应用的需求和规模自行设计分层结构。

  1. 路由层:负责定义路由和处理传入请求的处理程序。在这一层,你可以使用Gin的路由功能来定义URL路径和对应的处理函数。
  2. 处理层(处理器/服务层) :负责处理来自路由的请求,并将请求传递给适当的领域逻辑层。在这一层,你可以编写处理程序和服务,对请求进行验证、处理业务逻辑、操作数据库等。
  3. 领域逻辑层:处理业务逻辑的核心部分,独立于特定的框架。这一层包含了应用程序的核心业务规则和数据操作,与底层存储(如数据库)进行交互。
  4. 数据访问层:负责与数据存储(如数据库、缓存等)进行交互。这一层包含了对数据的持久化操作,如查询、写入和更新数据。
  5. 模型层:包含应用程序中使用的数据模型或结构。这一层定义了数据的结构和行为,以及与数据库交互时的ORM(对象关系映射)功能。

2.2 分层模块

  • controller模块:处理匹配的路由并调用处理中间件完成业务
  • main模块:完成服务的启动与配置
  • service模块:放置业务处理的中间件
  • uoload模块:动态生成文件存放地址,内含项目上传文件存放文件夹

3.实现服务

3.1 在upload中编写实现获取当前项目上传路径的文件

 package upload
 ​
 import (
    "path/filepath"
    "runtime"
 )
 ​
 func GetCurPath() (path string) {
     //获取运行文件的路径
    _, currentFilePath, _, _ := runtime.Caller(0)
     //获取运行文件所在的包
    projectPath := filepath.Dir(currentFilePath)
    return projectPath
 }

3.2 在service层编写文件上传下载的中间件

  • 文件上传原理

1.单文件:从form-data表单中获取MultiPartFile,再从gin的上下文对象的FormFile中获取,用随机文件名进行存储(需要先获取项目文件存储路径)

2.多文件:先从gin的上下文对象中获取MultiPartForm文件列表,然后从列表中['字段名']获得上传的文件列表,然后依次进行单文件上传操作即可

  • 单文件上传实现
 package service
 ​
 import (
    "fileUploadAndDownload/upload"
    "github.com/gin-gonic/gin"
    "github.com/google/uuid"
    "log"
    "net/http"
    "strings"
 )
 ​
 // 实现单文件上传的中间件
 func SingleFileUploadMidWare(c *gin.Context) {
    projectPath := upload.GetCurPath()
    //直接从formfile中获得文件
    file, _ := c.FormFile("file")
    filename := file.Filename
    extename := filename[strings.Index(filename, "."):]
    uuid := uuid.New()
    filename = uuid.String() + extename
    log.Printf(filename)
    //"E:/webServer/golang/file_test/upload"+"/images/"绝对路径测试
    c.SaveUploadedFile(file, projectPath+"/images/"+filename)
    log.Printf("/upload/images/" + filename)
    c.JSON(http.StatusOK, gin.H{
       "msg": "上传成功",
    })
 }
  • 多文件上传实现
 package service
 ​
 import (
    "fileUploadAndDownload/upload"
    "github.com/gin-gonic/gin"
    "github.com/google/uuid"
    "log"
    "net/http"
    "strconv"
    "strings"
 )
 ​
 // 实现单文件上传的中间件
 func MultiFileUploadMidWare(c *gin.Context) {
    projectPath := upload.GetCurPath()
    //先获得包含所有文件的一个文件列表
    form, _ := c.MultipartForm()
    //从文件列表中获得所有键为files的文件
    files := form.File["files"]
    fileCount := len(files)
    //遍历文件列表进行存储
    for _, file := range files {
       filename := file.Filename
       extename := filename[strings.Index(filename, "."):]
       uuid := uuid.New()
       filename = uuid.String() + extename
       log.Printf(filename)
       //"E:/webServer/golang/file_test/upload"+"/images/"绝对路径测试
       c.SaveUploadedFile(file, projectPath+"/images/"+filename)
       log.Printf("/upload/images/" + filename)
    }
    c.JSON(http.StatusOK, gin.H{
       "msg": "上传成功,共" + strconv.Itoa(fileCount) + "个文件",
    })
 }
  • 文件下载原理

直接用gin的context对象File方法传入文件名即可将对应文件返回

  • 实现
 package service
 ​
 import (
    "fileUploadAndDownload/upload"
    "github.com/gin-gonic/gin"
    "log"
 )
 ​
 func FileDownloadMidware(fileName string, c *gin.Context) {
    projectPath := upload.GetCurPath()
    log.Println(projectPath + "/images/" + fileName)
    c.File(projectPath + "/images/" + fileName)
 }

3.3 在controller中编写控制器,调用中间件完成业务(较简单,不再多叙述)

  • 单文件上传控制器
 package controller
 ​
 import (
    "fileUploadAndDownload/service"
    "github.com/gin-gonic/gin"
 )
 ​
 func SingleFileUpload(r *gin.Engine) {
    //路由分组
    apiRouter := r.Group("/singleFile")
    {
       apiRouter.POST("/upload", service.SingleFileUploadMidWare)
    }
 }
  • 多文件上传控制器
 package controller
 ​
 import (
    "fileUploadAndDownload/service"
    "github.com/gin-gonic/gin"
 )
 ​
 func MultiFileUpload(r *gin.Engine) {
    apiRouter := r.Group("/multiFile")
    {
       apiRouter.POST("/upload", service.MultiFileUploadMidWare)
    }
 }
  • 文件下载控制器
 package controller
 ​
 import (
    "fileUploadAndDownload/service"
    "github.com/gin-gonic/gin"
    "log"
 )
 ​
 func FileDownload(r *gin.Engine) {
    apiRouter := r.Group("/download")
    {
       apiRouter.GET("/:fileName", func(c *gin.Context) {
          fileName := c.Param("fileName")
          log.Println(fileName)
          service.FileDownloadMidware(fileName, c)
       })
    }
 }

3.4 在mian包中配置服务

  • 创建gin对象
 r := gin.Default()
  • 设置文件上传大小
 r.MaxMultipartMemory = 10 << 20 //限制文件上传大小为10MB
  • 配置文件上传下载的控制器
 //为单文件和多文件上传配置处理
 controller.SingleFileUpload(r)
 controller.MultiFileUpload(r)
 controller.FileDownload(r)
  • 启动服务
 const PORT = 3001
 r.Run(":" + strconv.Itoa(PORT))

4.效果

4.1 单文件上传

image.png

image.png

image.png

4.2 多文件上传

image.png

image.png

image.png

4.3 文件下载

image.png

image.png