|
@@ -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
|
|
|
+}
|