package handler import ( "net/http" "path/filepath" "strconv" "strings" "github.com/Nanqipro/YunQue-Tech-Projects/ai_english_learning/serve/internal/service" "github.com/gin-gonic/gin" ) // UploadHandler 文件上传处理器 type UploadHandler struct { uploadService service.UploadService } // NewUploadHandler 创建文件上传处理器 func NewUploadHandler() *UploadHandler { uploadService := service.NewUploadService("./uploads", "http://localhost:8080") return &UploadHandler{ uploadService: uploadService, } } // UploadAudio 上传音频文件 func (h *UploadHandler) UploadAudio(c *gin.Context) { // 获取上传的文件 file, err := c.FormFile("audio") if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": "获取文件失败", "details": err.Error(), }) return } // 验证文件类型 ext := strings.ToLower(filepath.Ext(file.Filename)) allowedTypes := []string{".mp3", ".wav", ".m4a", ".aac"} isValidType := false for _, allowedType := range allowedTypes { if ext == allowedType { isValidType = true break } } if !isValidType { c.JSON(http.StatusBadRequest, gin.H{ "error": "不支持的文件类型", "details": "只支持 mp3, wav, m4a, aac 格式", }) return } // 验证文件大小 (最大10MB) maxSize := int64(10 * 1024 * 1024) if file.Size > maxSize { c.JSON(http.StatusBadRequest, gin.H{ "error": "文件过大", "details": "文件大小不能超过10MB", }) return } // 使用上传服务保存文件 result, err := h.uploadService.UploadAudio(file) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": "文件上传失败", "details": err.Error(), }) return } // 返回上传结果 c.JSON(http.StatusOK, gin.H{ "message": "音频文件上传成功", "data": result, }) } // UploadImage 上传图片文件 func (h *UploadHandler) UploadImage(c *gin.Context) { // 获取上传的文件 file, err := c.FormFile("image") if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": "获取文件失败", "details": err.Error(), }) return } // 验证文件类型 ext := strings.ToLower(filepath.Ext(file.Filename)) allowedTypes := []string{".jpg", ".jpeg", ".png", ".gif", ".webp"} isValidType := false for _, allowedType := range allowedTypes { if ext == allowedType { isValidType = true break } } if !isValidType { c.JSON(http.StatusBadRequest, gin.H{ "error": "不支持的文件类型", "details": "只支持 jpg, jpeg, png, gif, webp 格式", }) return } // 验证文件大小 (最大5MB) maxSize := int64(5 * 1024 * 1024) if file.Size > maxSize { c.JSON(http.StatusBadRequest, gin.H{ "error": "文件过大", "details": "文件大小不能超过5MB", }) return } // 使用上传服务保存文件 result, err := h.uploadService.UploadImage(file) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": "文件上传失败", "details": err.Error(), }) return } // 返回上传结果 c.JSON(http.StatusOK, gin.H{ "message": "图片文件上传成功", "data": result, }) } // DeleteFile 删除文件 func (h *UploadHandler) DeleteFile(c *gin.Context) { fileID := c.Param("file_id") if fileID == "" { c.JSON(http.StatusBadRequest, gin.H{ "error": "File ID is required", }) return } // TODO: 实现实际的文件删除逻辑 // 目前返回模拟响应 c.JSON(http.StatusOK, gin.H{ "message": "File deleted successfully", "data": gin.H{ "file_id": fileID, "deleted": true, }, }) } // GetFileInfo 获取文件信息 func (h *UploadHandler) GetFileInfo(c *gin.Context) { fileID := c.Param("file_id") if fileID == "" { c.JSON(http.StatusBadRequest, gin.H{ "error": "File ID is required", }) return } // TODO: 实现实际的文件信息查询逻辑 // 目前返回模拟数据 result := gin.H{ "file_id": fileID, "filename": "example.mp3", "size": 1024000, "url": "/uploads/audio/" + fileID + ".mp3", "type": "audio", "format": "mp3", "upload_at": "2024-01-15T10:30:00Z", } c.JSON(http.StatusOK, gin.H{ "message": "File information retrieved", "data": result, }) } // GetUploadStats 获取上传统计 func (h *UploadHandler) GetUploadStats(c *gin.Context) { // 获取查询参数 days := c.DefaultQuery("days", "30") daysInt, err := strconv.Atoi(days) if err != nil || daysInt <= 0 { daysInt = 30 } // TODO: 实现实际的统计查询逻辑 // 目前返回模拟数据 stats := gin.H{ "period_days": daysInt, "total_files": 156, "audio_files": 89, "image_files": 67, "total_size": "245.6MB", "average_size": "1.6MB", "upload_trend": []gin.H{ {"date": "2024-01-10", "count": 12}, {"date": "2024-01-11", "count": 8}, {"date": "2024-01-12", "count": 15}, {"date": "2024-01-13", "count": 10}, {"date": "2024-01-14", "count": 18}, }, } c.JSON(http.StatusOK, gin.H{ "message": "Upload statistics", "data": stats, }) }