飞道的博客

【Golang】gin上传文件并且返回文件地址

602人阅读  评论(0)

又是很久没写博客了。写点基础的记录一下。

功能

  1. 上传文件
  2. 修改文件名称
  3. 保存到数据库
  4. 返回一个可访问的静态文件地址

环境

基础环境不太相同的,此博文仅供参考

  • gin : 1.7.1
  • golang : 1.16
  • gorm : 1.21.9

路由

// routes.go
import (
	"github.com/gin-gonic/gin"
	"net/http"
	"项目/controller"
	"项目/middleware"
	"项目/routes"
)

func collectRoutes(r *gin.Engine) *gin.Engine {
   
	// ------- 1. 使用中间件 这一步可以没有
	// r.Use(middleware.CORSMiddleware(),middleware.RecoveryMiddleware())
	// ------- 1. over
	// routes 是路由嵌套,不懂得可以百度一下
	routes.FileRoute(r)

	r.StaticFS("/static", http.Dir("./files"))
	return r
}
// routes/fileRoute.go
import (
	"github.com/gin-gonic/gin"
	"项目/controller"
)
func FileRoute(r *gin.Engine) *gin.Engine{
   
	kgFile := r.Group("/file")
	//kgFile.Use(middleware.AuthMiddleware())
	fileController := controller.NewFileController()
	kgFile.POST("",fileController.Upload)
	return r
}

controller


import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/spf13/viper"
	"gorm.io/gorm"
	"math/rand"
	"net"
	"os"
	"path"
	"pdmc/common"
	"pdmc/model"
	"pdmc/response"
	"regexp"
	"strconv"
	"strings"
	"time"
)
/*
 下面是用MVC思想写的...,其实可以不用
 IFileController
 FileController
 只需要在Upload方法去掉(f FileController)就行,但是后面需要自己想办法获取DB
*/
type IFileController interface {
   
	RestController
	Upload(ctx *gin.Context)
	Relate(ctx *gin.Context)
}

type FileController struct {
   
	*gorm.DB
}

// 上传文件
func (f FileController) Upload(ctx *gin.Context) {
   
	// 1. 获取文件
	// 2. 重命名文件
	// 3. 上传/保存到服务器
	// 4. 将文件路径保存到数据库
	// 5. 返回完整文件路径

	//	获取文件
	file, err := ctx.FormFile("file")
	if err != nil {
   
		panic(err.Error())
		return
	}

	// 重新命名文件
	newFileName := strconv.FormatInt(time.Now().Unix(),10) + strconv.Itoa(rand.Intn(999999-100000)+10000) + path.Ext(file.Filename)

	// 保存到服务器
	uperr := ctx.SaveUploadedFile(file, "./files/"+newFileName)
	if uperr != nil {
   
		fmt.Println(uperr)
		response.Fail(ctx,nil,"文件上传失败!")
		return
	}

	// 将文件路径保存到数据库
	fileInfo := &model.File{
   
		Name:     file.Filename,
		Address:  "/files/"+newFileName,
	}

	res := f.DB.Create(&fileInfo)
	if res.Error != nil {
   
		response.Fail(ctx,nil,"上传文件成功!数据库写入失败!")
		return
	}
	// 获取本机ip地址
	ipAddrList,_ := net.InterfaceAddrs()
	ipAddr := fetchIPAddr(ipAddrList)
	// 本机port
	port := viper.GetString("server.port")
	// 文件id
	fileId := fileInfo.ID
	fileAddress := ipAddr+":"+port+"/static/"+newFileName
	response.Success(ctx, gin.H{
   "file_addr":fileAddress,"id":fileId}, "上传成功!")
}

算了,信不过你们自己改

不存数据库的Controller版本

import (
...
)

// 上传文件
func Upload(ctx *gin.Context) {
   
	// 1. 获取文件
	// 2. 重命名文件
	// 3. 上传/保存到服务器
	// 4. 返回完整文件路径

	//	获取文件
	file, err := ctx.FormFile("file")
	if err != nil {
   
		panic(err.Error())
		return
	}

	// 重新命名文件
	newFileName := strconv.FormatInt(time.Now().Unix(),10) + strconv.Itoa(rand.Intn(999999-100000)+10000) + path.Ext(file.Filename)

	// 保存到服务器
	uperr := ctx.SaveUploadedFile(file, "./files/"+newFileName)
	if uperr != nil {
   
		fmt.Println(uperr)
		response.Fail(ctx,nil,"文件上传失败!")
		return
	}

	// 获取本机ip地址
	ipAddrList,_ := net.InterfaceAddrs()
	ipAddr := fetchIPAddr(ipAddrList)
	// 本机port  这里的port是写在config文件里面的,这里可以直接替换为port
	// port := viper.GetString("server.port")
	port := 1438
	// 文件id
	fileId := fileInfo.ID
	fileAddress := ipAddr+":"+port+"/static/"+newFileName
	response.Success(ctx, gin.H{
   "file_addr":fileAddress,"id":fileId}, "上传成功!")
}

测试结果


ok,继续撸代码。


转载:https://blog.csdn.net/liu_jiachen/article/details/117258137
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场