cab-backend/internal/handlers/images.go
2026-03-30 21:00:35 +03:00

95 lines
2.1 KiB
Go

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 ""
}
}