package storage import ( "fmt" "net/http" "github.com/gin-gonic/gin" ) var defaultAllowedTypes = map[string]bool{ "image/jpeg": true, "image/png": true, "image/gif": true, "image/webp": true, "image/svg+xml": true, "application/pdf": true, } var defaultMaxSize int64 = 10 << 20 type UploadConfig struct { FieldName string MaxSize int64 AllowedTypes map[string]bool } func UploadMiddleware(cfg UploadConfig) gin.HandlerFunc { if cfg.FieldName == "" { cfg.FieldName = "file" } if cfg.MaxSize <= 0 { cfg.MaxSize = defaultMaxSize } if cfg.AllowedTypes == nil { cfg.AllowedTypes = defaultAllowedTypes } return func(c *gin.Context) { file, header, err := c.Request.FormFile(cfg.FieldName) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "file field required"}) c.Abort() return } if header.Size > cfg.MaxSize { file.Close() c.JSON(http.StatusRequestEntityTooLarge, gin.H{"error": fmt.Sprintf("file too large (max %d bytes)", cfg.MaxSize)}) c.Abort() return } contentType := header.Header.Get("Content-Type") if len(cfg.AllowedTypes) > 0 && !cfg.AllowedTypes[contentType] { file.Close() c.JSON(http.StatusUnsupportedMediaType, gin.H{"error": fmt.Sprintf("file type not allowed: %s", contentType)}) c.Abort() return } c.Set("upload_file", &File{ Name: header.Filename, ContentType: contentType, Size: header.Size, Reader: file, }) c.Next() file.Close() } }