95 lines
2.1 KiB
Go
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 ""
|
|
}
|
|
}
|