package handlers import ( "io" "net/http" "path/filepath" "strings" "game-admin/internal/config" "github.com/gin-gonic/gin" "github.com/google/uuid" ) type ImageHandler struct { cfg *config.Config } func NewImageHandler(cfg *config.Config) *ImageHandler { return &ImageHandler{cfg: cfg} } func (h *ImageHandler) Upload(c *gin.Context) { fileHeader, err := c.FormFile("file") if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "file is required"}) return } if fileHeader.Size == 0 { c.JSON(http.StatusBadRequest, gin.H{"error": "file is empty"}) return } file, err := fileHeader.Open() if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "could not open uploaded file"}) return } defer file.Close() sniff := make([]byte, 512) n, err := file.Read(sniff) if err != nil && err != io.EOF { c.JSON(http.StatusBadRequest, gin.H{"error": "could not read uploaded file"}) return } contentType := http.DetectContentType(sniff[:n]) if !strings.HasPrefix(contentType, "image/") { c.JSON(http.StatusBadRequest, gin.H{"error": "only image files are allowed"}) return } ext := strings.ToLower(filepath.Ext(fileHeader.Filename)) if ext == "" { ext = extensionFromContentType(contentType) } if ext == "" { ext = ".bin" } fileName := uuid.NewString() + ext relativePath := filepath.ToSlash(filepath.Join("images", fileName)) fullPath := filepath.Join(h.cfg.UploadDir, filepath.FromSlash(relativePath)) if err := c.SaveUploadedFile(fileHeader, fullPath); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "could not save uploaded file"}) return } url := strings.TrimRight(h.cfg.BaseURL, "/") + "/uploads/" + relativePath c.JSON(http.StatusCreated, gin.H{ "name": fileName, "path": "/uploads/" + relativePath, "url": url, "content_type": contentType, }) } func extensionFromContentType(contentType string) string { switch contentType { case "image/jpeg": return ".jpg" case "image/png": return ".png" case "image/gif": return ".gif" case "image/webp": return ".webp" case "image/svg+xml": return ".svg" default: return "" } }