123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- 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) {
- form, err := c.MultipartForm()
- if err != nil {
- apierr.AbortBadRequest(c, http.StatusBadRequest, xerr.Customf("No multipartForm: %s", err.Error()))
- return
- }
- files := form.File["uploads"]
- // 验证文件数量
- if len(files) == 0 {
- apierr.AbortBadRequest(c, http.StatusBadRequest, xerr.Custom("No files selected"))
- return
- }
- res, err := middleware.BackendOperation(c).OpsService.Photos(c, files)
- if err != nil {
- apierr.AbortBadRequest(c, http.StatusBadRequest, err)
- return
- }
- c.JSON(http.StatusOK, gin.H{"code": http.StatusOK, "Msg": "ok", "data": res})
- }
- 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) {
- filename := c.Param("name")
- videoPath := fmt.Sprintf("%s/files/video/%s", config.WorkDir, filename)
- // 打开视频文件
- file, err := os.Open(videoPath)
- if err != nil {
- c.JSON(http.StatusNotFound, gin.H{"error": "Video not found"})
- return
- }
- defer file.Close()
- fileInfo, err := file.Stat()
- if err != nil {
- c.JSON(http.StatusInternalServerError, gin.H{"error": "Could not get file info"})
- return
- }
- // 设置响应头
- c.Header("Content-Type", "video/mp4")
- c.Header("Content-Length", fmt.Sprintf("%d", fileInfo.Size()))
- // 流式传输文件内容
- http.ServeContent(c.Writer, c.Request, fileInfo.Name(), fileInfo.ModTime(), file)
- }
|