package handler import ( "net/http" "os" "path/filepath" "github.com/gin-gonic/gin" "sproutworkcollect-backend/internal/service" ) // MediaHandler serves static media files (images, videos, and downloadable assets). type MediaHandler struct { workSvc *service.WorkService rateLimiter *service.RateLimiter } // NewMediaHandler wires up a MediaHandler with its dependencies. func NewMediaHandler(workSvc *service.WorkService, rateLimiter *service.RateLimiter) *MediaHandler { return &MediaHandler{workSvc: workSvc, rateLimiter: rateLimiter} } // ServeImage handles GET /api/image/:work_id/:filename func (h *MediaHandler) ServeImage(c *gin.Context) { imgPath := filepath.Join( h.workSvc.WorksDir(), c.Param("work_id"), "image", c.Param("filename"), ) if _, err := os.Stat(imgPath); os.IsNotExist(err) { c.JSON(http.StatusNotFound, gin.H{"error": "图片不存在"}) return } c.File(imgPath) } // ServeVideo handles GET /api/video/:work_id/:filename func (h *MediaHandler) ServeVideo(c *gin.Context) { videoPath := filepath.Join( h.workSvc.WorksDir(), c.Param("work_id"), "video", c.Param("filename"), ) if _, err := os.Stat(videoPath); os.IsNotExist(err) { c.JSON(http.StatusNotFound, gin.H{"error": "视频不存在"}) return } c.File(videoPath) } // DownloadFile handles GET /api/download/:work_id/:platform/:filename func (h *MediaHandler) DownloadFile(c *gin.Context) { workID := c.Param("work_id") platform := c.Param("platform") filename := c.Param("filename") filePath := filepath.Join(h.workSvc.WorksDir(), workID, "platform", platform, filename) if _, err := os.Stat(filePath); os.IsNotExist(err) { c.JSON(http.StatusNotFound, gin.H{"error": "文件不存在"}) return } fp := service.Fingerprint(c.ClientIP(), c.GetHeader("User-Agent")) if h.rateLimiter.CanPerform(fp, "download", workID) { _ = h.workSvc.UpdateStats(workID, "download") } c.FileAttachment(filePath, filename) }