diff --git a/src/modules/common/common.go b/src/modules/common/common.go index 0a37ffdc..7d201a24 100644 --- a/src/modules/common/common.go +++ b/src/modules/common/common.go @@ -90,9 +90,11 @@ func Setup(router *gin.Engine) { // 文件操作处理 fileGroup := router.Group("/file") { - fileGroup.POST("/chunkCheck", middleware.PreAuthorize(nil), controller.NewFile.ChunkCheck) - fileGroup.POST("/chunkUpload", middleware.PreAuthorize(nil), controller.NewFile.ChunkUpload) - fileGroup.POST("/chunkMerge", middleware.PreAuthorize(nil), controller.NewFile.ChunkMerge) + fileGroup.POST("/upload2", middleware.PreAuthorize(nil), controller.NewFile.Upload2) + fileGroup.POST("/chunkCheck", middleware.PreAuthorize(nil), controller.NewFile.ChunkCheck2) + fileGroup.POST("/chunkUpload", middleware.PreAuthorize(nil), controller.NewFile.ChunkUpload2) + fileGroup.POST("/chunkMerge", middleware.PreAuthorize(nil), controller.NewFile.ChunkMerge2) + fileGroup.POST("/transferStaticFile", middleware.PreAuthorize(nil), controller.NewCommont.TransferStaticFile2) fileGroup.POST("/upload", middleware.PreAuthorize(nil), controller.NewFile.Upload) fileGroup.POST("/chunk-check", middleware.PreAuthorize(nil), controller.NewFile.ChunkCheck) diff --git a/src/modules/common/controller/file.go b/src/modules/common/controller/file.go index 52ad5b87..fc10e6e6 100644 --- a/src/modules/common/controller/file.go +++ b/src/modules/common/controller/file.go @@ -11,12 +11,16 @@ import ( "be.ems/src/framework/config" "be.ems/src/framework/constants" + "be.ems/src/framework/constants/uploadsubpath" "be.ems/src/framework/i18n" "be.ems/src/framework/reqctx" "be.ems/src/framework/resp" + "be.ems/src/framework/utils/ctx" "be.ems/src/framework/utils/file" + "be.ems/src/framework/vo/result" "github.com/gin-gonic/gin" + "github.com/gin-gonic/gin/binding" ) // 实例化控制层 FileController 结构体 @@ -446,3 +450,210 @@ func (s *FileController) TransferStaticFile(c *gin.Context) { urlPath := strings.Replace(newFile, dir, static["prefix"].(string), 1) c.JSON(200, resp.OkData(filepath.ToSlash(urlPath))) } + +// 上传文件 +// +// POST /upload +// +// @Tags common/file +// @Accept multipart/form-data +// @Produce json +// @Param file formData file true "The file to upload." +// @Param subPath formData string true "subpath, eg: default or common" Enums(default, common) +// @Success 200 {object} object "Response Results" +// @Security TokenAuth +// @Summary Upload a file +// @Description Upload a file, interface param use +// @Router /file/upload [post] +func (s *FileController) Upload2(c *gin.Context) { + language := ctx.AcceptLanguage(c) + // 上传的文件 + formFile, err := c.FormFile("file") + if err != nil { + c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + return + } + // 子路径 + subPath := c.PostForm("subPath") + if _, ok := uploadsubpath.UploadSubpath[subPath]; !ok { + c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + return + } + + // 上传文件转存 + upFilePath, err := file.TransferUploadFile(formFile, subPath, nil) + if err != nil { + c.JSON(200, result.ErrMsg(err.Error())) + return + } + + newFileName := upFilePath[strings.LastIndex(upFilePath, "/")+1:] + c.JSON(200, result.OkData(map[string]string{ + "url": "//" + c.Request.Host + upFilePath, + "fileName": upFilePath, + "newFileName": newFileName, + "originalFileName": formFile.Filename, + })) +} + +// 切片文件检查 +// +// POST /chunkCheck +// +// @Tags common/file +// @Accept json +// @Produce json +// @Param data body object true "Request Param" +// @Success 200 {object} object "Response Results" +// @Security TokenAuth +// @Summary Slice file checking +// @Description Slice file checking +// @Router /file/chunkCheck [post] +func (s *FileController) ChunkCheck2(c *gin.Context) { + language := ctx.AcceptLanguage(c) + var body struct { + // 唯一标识 + Identifier string `json:"identifier" binding:"required"` + // 文件名 + FileName string `json:"fileName" binding:"required"` + } + err := c.ShouldBindJSON(&body) + if err != nil { + c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + return + } + + // 读取标识目录 + chunks, err := file.ChunkCheckFile(body.Identifier, body.FileName) + if err != nil { + c.JSON(200, result.ErrMsg(err.Error())) + return + } + c.JSON(200, result.OkData(chunks)) +} + +// 切片文件合并 +// +// POST /chunkMerge +// +// @Tags common/file +// @Accept json +// @Produce json +// @Param data body object true "Request Param" +// @Success 200 {object} object "Response Results" +// @Security TokenAuth +// @Summary Slice file merge +// @Description Slice file merge +// @Router /file/chunkMerge [post] +func (s *FileController) ChunkMerge2(c *gin.Context) { + language := ctx.AcceptLanguage(c) + var body struct { + // 唯一标识 + Identifier string `json:"identifier" binding:"required"` + // 文件名 + FileName string `json:"fileName" binding:"required"` + // 子路径类型 + SubPath string `json:"subPath" binding:"required"` + } + err := c.ShouldBindJSON(&body) + if err != nil { + c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + return + } + if _, ok := uploadsubpath.UploadSubpath[body.SubPath]; !ok { + c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + return + } + + // 切片文件合并 + mergeFilePath, err := file.ChunkMergeFile(body.Identifier, body.FileName, body.SubPath) + if err != nil { + c.JSON(200, result.ErrMsg(err.Error())) + return + } + + newFileName := mergeFilePath[strings.LastIndex(mergeFilePath, "/")+1:] + c.JSON(200, result.OkData(map[string]string{ + "url": "//" + c.Request.Host + mergeFilePath, + "fileName": mergeFilePath, + "newFileName": newFileName, + "originalFileName": body.FileName, + })) +} + +// 切片文件上传 +// +// POST /chunkUpload +// +// @Tags common/file +// @Accept multipart/form-data +// @Produce json +// @Param file formData file true "The file to upload." +// @Param identifier formData string true "Slice Marker" +// @Param index formData string true "Slice No." +// @Success 200 {object} object "Response Results" +// @Security TokenAuth +// @Summary Sliced file upload +// @Description Sliced file upload +// @Router /file/chunkUpload [post] +func (s *FileController) ChunkUpload2(c *gin.Context) { + language := ctx.AcceptLanguage(c) + // 切片编号 + index := c.PostForm("index") + // 切片唯一标识 + identifier := c.PostForm("identifier") + // 上传的文件 + formFile, err := c.FormFile("file") + if index == "" || identifier == "" || err != nil { + c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + return + } + + // 上传文件转存 + chunkFilePath, err := file.TransferChunkUploadFile(formFile, index, identifier) + if err != nil { + c.JSON(200, result.ErrMsg(err.Error())) + return + } + c.JSON(206, result.OkData(chunkFilePath)) +} + +// 转存指定对应文件到静态目录 +// +// POST /transferStaticFile +func (s *CommontController) TransferStaticFile2(c *gin.Context) { + language := ctx.AcceptLanguage(c) + var body struct { + UploadPath string `json:"uploadPath" binding:"required"` + StaticPath string `json:"staticPath" binding:"required"` + Language string `json:"language" binding:"required"` + } + if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil { + c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + return + } + + // 取语言前缀 + lang := strings.SplitN(body.Language, "_", 2)[0] + + // 默认静态资源 + static := config.Get("staticFile.default").(map[string]any) + dir, err := filepath.Abs(static["dir"].(string)) + if err != nil { + c.JSON(400, result.CodeMsg(400, err.Error())) + return + } + + delPrefix := strings.Replace(body.StaticPath, static["prefix"].(string), "", 1) + staticPath := strings.Replace(delPrefix, "{language}", lang, 1) + newFile := filepath.ToSlash(fmt.Sprintf("%s%s", dir, staticPath)) + + err = file.CopyUploadFile(body.UploadPath, newFile) + if err != nil { + c.JSON(400, result.CodeMsg(400, err.Error())) + return + } + + urlPath := strings.Replace(newFile, dir, static["prefix"].(string), 1) + c.JSON(200, result.OkData(filepath.ToSlash(urlPath))) +}