|
@@ -1,15 +1,20 @@
|
|
|
package upload
|
|
|
|
|
|
import (
|
|
|
+ "bytes"
|
|
|
"fmt"
|
|
|
+ "io"
|
|
|
"kpt-pasture/config"
|
|
|
"kpt-pasture/http/middleware"
|
|
|
"net/http"
|
|
|
"os"
|
|
|
+ "path/filepath"
|
|
|
+ "time"
|
|
|
|
|
|
"gitee.com/xuyiping_admin/pkg/apierr"
|
|
|
"gitee.com/xuyiping_admin/pkg/xerr"
|
|
|
"github.com/gin-gonic/gin"
|
|
|
+ "github.com/xuri/excelize/v2"
|
|
|
)
|
|
|
|
|
|
func Photos(c *gin.Context) {
|
|
@@ -36,7 +41,145 @@ func Photos(c *gin.Context) {
|
|
|
}
|
|
|
|
|
|
func Files(c *gin.Context) {
|
|
|
+ // 获取上传的文件
|
|
|
+ file, err := c.FormFile("file")
|
|
|
+ if err != nil {
|
|
|
+ apierr.AbortBadRequest(c, http.StatusBadRequest, xerr.Customf("获取文件失败: %s", err.Error()))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查文件类型
|
|
|
+ ext := filepath.Ext(file.Filename)
|
|
|
+ if ext != ".xlsx" && ext != ".xls" {
|
|
|
+ apierr.AbortBadRequest(c, http.StatusBadRequest, xerr.Custom("只支持Excel文件(.xlsx, .xls)"))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查文件大小
|
|
|
+ if file.Size == 0 {
|
|
|
+ apierr.AbortBadRequest(c, http.StatusBadRequest, xerr.Custom("文件为空"))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 创建保存目录
|
|
|
+ uploadDir := fmt.Sprintf("%s/files/excel", config.WorkDir)
|
|
|
+ if err := os.MkdirAll(uploadDir, 0755); err != nil {
|
|
|
+ apierr.AbortBadRequest(c, http.StatusInternalServerError, xerr.Customf("创建目录失败: %s", err.Error()))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 生成唯一文件名
|
|
|
+ filename := fmt.Sprintf("%d%s", time.Now().UnixNano(), ext)
|
|
|
+ filePath := filepath.Join(uploadDir, filename)
|
|
|
+
|
|
|
+ // 保存文件
|
|
|
+ if err := c.SaveUploadedFile(file, filePath); err != nil {
|
|
|
+ apierr.AbortBadRequest(c, http.StatusInternalServerError, xerr.Customf("保存文件失败: %s", err.Error()))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 打开上传的文件
|
|
|
+ src, err := file.Open()
|
|
|
+ if err != nil {
|
|
|
+ apierr.AbortBadRequest(c, http.StatusInternalServerError, xerr.Customf("打开文件失败: %s", err.Error()))
|
|
|
+ return
|
|
|
+ }
|
|
|
+ defer src.Close()
|
|
|
+
|
|
|
+ // 读取文件内容
|
|
|
+ fileBytes, err := io.ReadAll(src)
|
|
|
+ if err != nil {
|
|
|
+ apierr.AbortBadRequest(c, http.StatusInternalServerError, xerr.Customf("读取文件内容失败: %s", err.Error()))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查文件头部签名
|
|
|
+ if len(fileBytes) < 8 {
|
|
|
+ apierr.AbortBadRequest(c, http.StatusBadRequest, xerr.Custom("文件格式不正确"))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查Excel文件签名
|
|
|
+ isExcel := false
|
|
|
+ if ext == ".xlsx" {
|
|
|
+ // XLSX文件签名
|
|
|
+ if bytes.Equal(fileBytes[:4], []byte{0x50, 0x4B, 0x03, 0x04}) {
|
|
|
+ isExcel = true
|
|
|
+ }
|
|
|
+ } else if ext == ".xls" {
|
|
|
+ // XLS文件签名
|
|
|
+ if bytes.Equal(fileBytes[:8], []byte{0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1}) {
|
|
|
+ isExcel = true
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if !isExcel {
|
|
|
+ apierr.AbortBadRequest(c, http.StatusBadRequest, xerr.Custom("文件格式不正确,请确保上传的是有效的Excel文件"))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 读取Excel文件
|
|
|
+ options := excelize.Options{
|
|
|
+ RawCellValue: true,
|
|
|
+ }
|
|
|
+ f, err := excelize.OpenReader(bytes.NewReader(fileBytes), options)
|
|
|
+ if err != nil {
|
|
|
+ // 如果直接读取失败,尝试从保存的文件读取
|
|
|
+ f, err = excelize.OpenFile(filePath)
|
|
|
+ if err != nil {
|
|
|
+ apierr.AbortBadRequest(c, http.StatusInternalServerError, xerr.Customf("读取Excel文件失败,请确保文件格式正确: %s", err.Error()))
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+ defer f.Close()
|
|
|
+
|
|
|
+ // 获取第一个工作表
|
|
|
+ sheetName := f.GetSheetName(0)
|
|
|
+ rows, err := f.GetRows(sheetName)
|
|
|
+ if err != nil {
|
|
|
+ apierr.AbortBadRequest(c, http.StatusInternalServerError, xerr.Customf("读取工作表失败: %s", err.Error()))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理Excel数据
|
|
|
+ if len(rows) < 2 {
|
|
|
+ apierr.AbortBadRequest(c, http.StatusBadRequest, xerr.Custom("Excel文件数据为空"))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取表头并转换为中文
|
|
|
+ headers := rows[0]
|
|
|
+ headerMap := make(map[string]string)
|
|
|
+ for _, header := range headers {
|
|
|
+ headerMap[header] = header
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理数据行
|
|
|
+ var data []map[string]string
|
|
|
+ for i, row := range rows[1:] {
|
|
|
+ if len(row) != len(headers) {
|
|
|
+ apierr.AbortBadRequest(c, http.StatusBadRequest, xerr.Customf("第%d行数据列数与表头不匹配", i+2))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ rowData := make(map[string]string)
|
|
|
+ for j, cell := range row {
|
|
|
+ rowData[headers[j]] = cell
|
|
|
+ }
|
|
|
+ data = append(data, rowData)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 调用后端服务处理数据
|
|
|
+ if err := middleware.BackendOperation(c).OpsService.ImportExcel(c, data); err != nil {
|
|
|
+ apierr.AbortBadRequest(c, http.StatusBadRequest, err)
|
|
|
+ return
|
|
|
+ }
|
|
|
|
|
|
+ c.JSON(http.StatusOK, gin.H{
|
|
|
+ "code": http.StatusOK,
|
|
|
+ "msg": "导入成功",
|
|
|
+ "data": nil,
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
func OssVideo(c *gin.Context) {
|