Browse Source

批量上传素材

xyxie 4 months ago
parent
commit
1bfd1f50f1

+ 157 - 0
controllers/material/material.go

@@ -5,10 +5,15 @@ import (
 	"eta/eta_api/controllers"
 	"eta/eta_api/models"
 	"eta/eta_api/models/material"
+	"eta/eta_api/services"
 	materialService "eta/eta_api/services/material"
 	"eta/eta_api/utils"
 	"fmt"
 	"github.com/rdlucklib/rdluck_tools/paging"
+	"io"
+	"os"
+	"path"
+	"path/filepath"
 	"strings"
 	"time"
 )
@@ -1021,3 +1026,155 @@ func (this *MaterialController) MaterialClassifyList() {
 	br.Msg = "获取成功"
 	br.Data = resp
 }
+
+// BatchAdd
+// @Title 批量新增素材
+// @Description 新增/编辑保存素材库接口
+// @Param	request	body material.AddAndEditSandbox true "type json string"
+// @Success 200 {object} material.Material
+// @router /batch/add [post]
+func (this *MaterialController) BatchAdd() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	classifyId, _ := this.GetInt("ClassifyId", 0)
+	if classifyId <= 0 {
+		br.Msg = "请选择分类"
+		return
+	}
+	materialNames := this.GetStrings("MaterialNames")
+	if len(materialNames) == 0 {
+		br.Msg = "请填写图片名称"
+		return
+	}
+
+	// 判断文件名是否已存在
+	count, err := material.GetMaterialCountByNames(materialNames)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	if count > 0 {
+		br.Msg = "图片名称已存在,请重新填写"
+		return
+	}
+	// 获取表单中的所有文件
+	files, err := this.GetFiles("Files")
+	if err != nil {
+		br.Msg = "文件上传失败"
+		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+		return
+	}
+	if len(files) == 0 {
+		br.Msg = "请选择文件"
+		return
+	}
+	if len(materialNames) != len(files) {
+		br.Msg = "图片数量与名称数量不一致"
+		return
+	}
+	// 限制上传文件的大小(可选)
+	maxSize := int64(10 << 20) // 10MB
+	for _, file := range files {
+		if file.Size > maxSize {
+			br.Msg = "文件大小超过限制"
+			return
+		}
+	}
+
+	// 创建目标目录(如果不存在)
+	uploadDir := utils.STATIC_DIR + "hongze/" + time.Now().Format("20060102")
+	if err = os.MkdirAll(uploadDir, utils.DIR_MOD); err != nil {
+		br.Msg = "存储目录创建失败"
+		br.ErrMsg = "存储目录创建失败, Err:" + err.Error()
+		return
+	}
+
+	// 处理单个文件(这里假设files是一个多文件字段)
+	// 实际上,当使用<input type="file" name="files" multiple>时,
+	// 它会作为多个文件字段发送到服务器,名字相同但后缀不同,例如:files, files[1], files[2]等。
+	// 所以我们需要遍历这些字段。
+
+	// 创建一个map来存储所有文件
+	fileUrlMap := make(map[string]string)
+
+	// 获取上传文件的头部信息
+	//fileHeaders := this.Ctx.Request.Header["Content-Disposition"]
+	for k, fileHeader := range files {
+		// 解析Content-Disposition头以获取文件名
+		// 获取文件名(避免路径遍历攻击,只使用文件名部分)
+		fileName := filepath.Base(fileHeader.Filename)
+		fileName = strings.TrimSpace(strings.Replace(fileName, "\\", "/", -1)) // 替换可能存在的反斜杠
+		fileName = strings.Trim(fileName, " \"\n\r\t")                         // 去除文件名两侧的空白字符和引号
+
+		ext := path.Ext(fileName)
+		ossFileName := utils.GetRandStringNoSpecialChar(28) + ext
+		filePath := filepath.Join(uploadDir, ossFileName)
+
+		// 创建目标文件
+		dst, e := os.Create(filePath)
+		if e != nil {
+			br.Msg = "文件创建失败"
+			br.ErrMsg = "文件创建失败, Err:" + e.Error()
+			//http.Error(w, e.Error(), http.StatusInternalServerError)
+			return
+		}
+		defer dst.Close()
+		src, e := fileHeader.Open()
+		if e != nil {
+			br.Msg = "文件打开失败"
+			br.ErrMsg = "文件打开失败, Err:" + e.Error()
+			return
+		}
+		// 将上传的文件内容复制到目标文件
+		if _, err = io.Copy(dst, src); err != nil {
+			br.Msg = "文件保存失败"
+			br.ErrMsg = "文件保存失败, Err:" + err.Error()
+			return
+		}
+
+		defer func() {
+			_ = os.Remove(filePath)
+		}()
+		// 上传到阿里云
+		ossDir := utils.RESOURCE_DIR + "cloud_disk/"
+
+		savePath := ossDir + time.Now().Format("200601/20060102/") + ossFileName
+		ossClient := services.NewOssClient()
+		if ossClient == nil {
+			br.Msg = "上传失败"
+			br.ErrMsg = "初始化OSS服务失败"
+			return
+		}
+		resourceUrl, e := ossClient.UploadFile(ossFileName, filePath, savePath)
+		if e != nil {
+			br.Msg = "文件上传失败"
+			br.ErrMsg = "文件上传失败,Err:" + e.Error()
+			return
+		}
+
+		// 将文件保存到map中(这里主要是为了演示,实际使用中可能不需要)
+		fileUrlMap[materialNames[k]] = resourceUrl
+	}
+
+	err = materialService.BatchAddMaterial(fileUrlMap, classifyId, sysUser.AdminId, sysUser.AdminName)
+	if err != nil {
+		br.Msg = "文件上传失败"
+		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+		return
+	}
+	msg := "上传成功"
+	br.Ret = 200
+	br.Success = true
+	br.Msg = msg
+}

+ 22 - 0
models/material/material.go

@@ -326,3 +326,25 @@ func GetMaterialInfoCountByClassifyIds(classifyIds []string) (count int, err err
 	err = o.Raw(sql, classifyIds).QueryRow(&count)
 	return
 }
+
+func GetMaterialCountByNames(materialNames []string) (count int, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT COUNT(1) AS count FROM material WHERE material_name in(` + utils.GetOrmInReplace(len(materialNames)) + `)`
+	err = o.Raw(sql, materialNames).QueryRow(&count)
+	return
+}
+
+func GetMaterialCountByName(materialName string) (count int, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT COUNT(1) AS count FROM material WHERE material_name=? `
+	err = o.Raw(sql, materialName).QueryRow(&count)
+	return
+}
+
+// GetMaterialMaxSort 获取最大的排序数
+func GetMaterialMaxSort() (sort int, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT MAX(sort) AS sort FROM material `
+	err = o.Raw(sql).QueryRow(&sort)
+	return
+}

+ 9 - 0
routers/commentsRouter.go

@@ -7360,6 +7360,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_api/controllers/material:MaterialController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/material:MaterialController"],
+        beego.ControllerComments{
+            Method: "BatchAdd",
+            Router: `/batch/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_api/controllers/material:MaterialController"] = append(beego.GlobalControllerRouter["eta/eta_api/controllers/material:MaterialController"],
         beego.ControllerComments{
             Method: "AddMaterialClassify",

+ 31 - 6
services/material/material.go

@@ -44,7 +44,7 @@ func MaterialClassifyItemsMakeTree(sysUser *system.Admin, allNode []*material.Ma
 	}
 }
 
-// GetMaterialClassifyListForMe 获取我创建的沙盘
+// GetMaterialClassifyListForMe 获取我创建的素材
 func GetMaterialClassifyListForMe(adminInfo system.Admin, resp *material.MaterialClassifyListResp, classifyId int) (errMsg string, err error) {
 
 	classifyAll, err := material.GetMaterialClassifyByParentId(classifyId)
@@ -62,10 +62,35 @@ func GetMaterialClassifyListForMe(adminInfo system.Admin, resp *material.Materia
 	return
 }
 
-// AddMaterial 新增沙盘
+func BatchAddMaterial(materialMap map[string]string, classifyId, opUserId int, opUserName string) (err error) {
+	materialList := make([]*material.Material, 0)
+	sort, err := material.GetMaterialMaxSort()
+	if err != nil {
+		return
+	}
+	for k, v := range materialMap {
+		sort = sort + 1
+		materialList = append(materialList, &material.Material{
+			MaterialName: k,
+			ImgUrl:       v,
+			SysUserId:    opUserId,
+			SysUserName:  opUserName,
+			ModifyTime:   time.Now(),
+			CreateTime:   time.Now(),
+			ClassifyId:   classifyId,
+			Sort:         sort,
+		})
+	}
+	if len(materialList) > 0 {
+		err = material.AddMultiMaterial(materialList)
+	}
+	return
+}
+
+// AddMaterial 新增素材
 func AddMaterial(req material.AddAndEditMaterial, opUserId int, opUserName string) (resp *material.MaterialSaveResp, err error) {
 	resp = new(material.MaterialSaveResp)
-	//沙盘主表信息
+	//素材主表信息
 	materialInfo := &material.Material{
 		MaterialName: utils.TrimStr(req.MaterialName),
 		ImgUrl:       utils.TrimStr(req.ImgUrl),
@@ -77,7 +102,7 @@ func AddMaterial(req material.AddAndEditMaterial, opUserId int, opUserName strin
 		Sort:         0,
 	}
 
-	//新增沙盘
+	//新增素材
 	id, err := material.AddMaterial(materialInfo)
 	if err != nil {
 		return
@@ -142,9 +167,9 @@ func materialClassifyHaveChildV2(allNode []*material.MaterialClassifyItems, node
 	return
 }
 
-// DeleteMaterial 删除沙盘
+// DeleteMaterial 删除素材
 func DeleteMaterial(materialId int) (err error) {
-	// 获取沙盘主表信息
+	// 获取素材主表信息
 	/*materialInfo, err := materialId.dele(materialId)
 	if err != nil {
 		return