在web开发中我们一般会进行一些让用户进行文件上传的操作,本章节主要结合gin框架
进行搭建一个文件上传的操作,以多文件上传为主,因为多文件
也可以上传单文件,一些特殊的场景可能使用的是单文件上传,但是也可以根据判断上传文件的len()
进行取舍是否同意通过改请求。下列的写法是参照go-vue-admin开源项目(gva)
的写法进行创建的
upload:
size: 2 # 设置限制上传的大小
path: uploads/file # 上传的路径
通过读取yaml文件的配置信息进行定义结构体,我们在config包下创建一个conf_upload.go 来装我们的结构体
package config
type Upload struct {
Size int `json:"size" yaml:"size"` // 图片上传的大小
Path string `json:"path" yaml:"path"` // 图片上传的目录
}
虽然我们在config包下进行创建一个入口文件enter.go,将我们的结构体帮定进去
type Config struct {
Upload Upload `yaml:"upload"`
}
然后在根目录创建一个global文件夹,并且创建global.go 文件,将其注册为全局。这样的好处是我们在拓展多个业务的时候方便我们进行快速的拓展,比如我们的全局DB也可以放置在这里,初始化的时候就可以附值。该方法做了:文件限制的大小,是否重复上传,是否有存储路径等判断!
var (
Config *config.Config
// DB *gorm.DB
)
根目录下创建api包并且创建一个images_api/settings_upload.go
package images_api
import (
"fmt"
"github.com/gin-gonic/gin"
"gvb-server/global"
"gvb-server/models/response"
"io/fs"
"os"
"path"
)
type FileUploadResponse struct {
IsSuccess bool `json:"is_success"` // 是否上传成功
FileName string `json:"file_name"` // 文件名
Msg string `json:"msg"` // 消息
}
// ImagesUploadApi 上传单个图片,返回的是图片的url地址
func (ImagesApi) ImagesUploadApi(c *gin.Context) {
// 上传多个文件
form, err := c.MultipartForm()
if err != nil {
response.FailWithMessage(response.ErrorUploadImage, c)
return
}
// 前端的字段定义是images
fileList, ok := form.File["images"]
if !ok {
response.FailWithMessage(response.ErrorNotMessage, c)
return
}
// 判断路径是否存在
basePath := global.Config.Upload.Path
_, err = os.ReadDir(basePath)
if err != nil {
// 递归创建
err = os.MkdirAll(basePath, fs.ModePerm)
if err != nil {
global.Log.Error(err)
}
}
// 不存在就创建
var resultList []FileUploadResponse
for _, file := range fileList {
filePath := path.Join(basePath, file.Filename)
// 判断大小
size := float64(file.Size) / float64(1024*1024)
if size >= float64(global.Config.Upload.Size) {
resultList = append(resultList, FileUploadResponse{
IsSuccess: false,
FileName: file.Filename,
Msg: fmt.Sprintf("图片大小超过设定大小为:%dMB,当前图片大小为%.2fMB", global.Config.Upload.Size, size),
})
continue
}
err = c.SaveUploadedFile(file, filePath)
if err != nil {
resultList = append(resultList, FileUploadResponse{
IsSuccess: false,
FileName: file.Filename,
Msg: err.Error(),
})
}
resultList = append(resultList, FileUploadResponse{
IsSuccess: true,
FileName: filePath,
Msg: "上传成功",
})
}
// 自己封装的输出方法
response.SuccessDate(resultList, c)
}
在根目录创建一个router文件,先创建一个入口文件enter.go文件,然后创建一个images_router.go
// enter.go
package router
type RouterGroup struct {
*gin.RouterGroup
}
func InitRouter() *gin.Engine {
gin.SetMode(global.Config.System.Env)
router := gin.Default()
apiRouterGroup := router.Group("api")
routerGroupApp := RouterGroup{apiRouterGroup}
routerGroupApp.ImagesRouter()
return router
}
// images_router.go
package router
func (router RouterGroup) ImagesRouter() {
app := api.ApiGroupApp.ImagesApi
router.POST("images", app.ImagesUploadApi)
}