package api import ( "fmt" "licserver/internal/service" "net/http" "os" "path/filepath" "strconv" "strings" "time" "github.com/gin-gonic/gin" ) type UploadHandler struct { uploadService *service.UploadService } func NewUploadHandler(uploadService *service.UploadService) *UploadHandler { return &UploadHandler{uploadService: uploadService} } func (h *UploadHandler) UploadFile(c *gin.Context) { file, err := c.FormFile("file") if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "未找到上传文件"}) return } deviceUID := c.PostForm("device_uid") description := c.PostForm("description") userID := c.GetUint("userID") upload, err := h.uploadService.UploadFile(file, userID, deviceUID, description) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, upload) } func (h *UploadHandler) DownloadFile(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "无效的文件ID"}) return } file, err := h.uploadService.DownloadFile(uint(id)) if err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "文件不存在"}) return } c.FileAttachment(file.FilePath, file.FileName) } func (h *UploadHandler) DeleteFile(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "无效的文件ID"}) return } userID := c.GetUint("userID") if err := h.uploadService.DeleteFile(uint(id), userID); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "文件删除成功"}) } func (h *UploadHandler) GetDeviceFiles(c *gin.Context) { deviceUID := c.Param("uid") files, err := h.uploadService.GetDeviceFiles(deviceUID) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, files) } func (h *UploadHandler) UploadChunk(c *gin.Context) { file, err := c.FormFile("chunk") if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "未找到上传文件"}) return } fileHash := c.PostForm("fileHash") if fileHash == "" { c.JSON(http.StatusBadRequest, gin.H{"error": "未提供文件哈希"}) return } chunkNumber, err := strconv.Atoi(c.PostForm("chunkNumber")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "无效的分片序号"}) return } totalChunks, err := strconv.Atoi(c.PostForm("totalChunks")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "无效的总分片数"}) return } totalSize, err := strconv.ParseInt(c.PostForm("totalSize"), 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "无效的文件大小"}) return } filename := c.PostForm("filename") deviceUID := c.PostForm("deviceUID") userID := c.GetUint("userID") err = h.uploadService.UploadChunk( file, fileHash, chunkNumber, totalChunks, totalSize, filename, userID, deviceUID, ) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } // 检查是否所有分片都已上传 completed, err := h.uploadService.CheckUploadStatus(fileHash) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{ "message": "分片上传成功", "completed": completed, }) } func (h *UploadHandler) MergeChunks(c *gin.Context) { fileHash := c.PostForm("fileHash") if fileHash == "" { c.JSON(http.StatusBadRequest, gin.H{"error": "未提供文件哈希"}) return } upload, err := h.uploadService.MergeChunks(fileHash) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{ "message": "文件合并成功", "file": upload, }) } func (h *UploadHandler) UploadSiteFile(c *gin.Context) { file, err := c.FormFile("file") if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "未找到上传文件"}) return } // 检查文件类型 ext := strings.ToLower(filepath.Ext(file.Filename)) allowedExts := map[string]bool{ ".jpg": true, ".jpeg": true, ".png": true, ".gif": true, ".ico": true, ".svg": true, } if !allowedExts[ext] { c.JSON(http.StatusBadRequest, gin.H{"error": "不支持的文件类型"}) return } // 生成文件名 filename := fmt.Sprintf("site_%s%s", time.Now().Format("20060102150405"), ext) // 构建目标目录路径 uploadDir := filepath.Join("web", "static", "images") if err := os.MkdirAll(uploadDir, 0755); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "创建目录失败"}) return } // 构建完整的文件路径 filePath := filepath.Join(uploadDir, filename) // 保存文件 if err := c.SaveUploadedFile(file, filePath); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "保存文件失败"}) return } // 返回文件URL(使用正斜杠作为URL路径分隔符) fileURL := "/" + strings.Join([]string{"static", "images", filename}, "/") c.JSON(http.StatusOK, gin.H{ "url": fileURL, "message": "文件上传成功", }) }