package helper import ( "fmt" "io" "mime/multipart" "os" "path/filepath" "strings" "time" "github.com/google/uuid" ) const ( MaxFileSize = 5 << 20 // 5MB TowerUploadDir = "./uploads/towers" DeviceUploadDir = "./uploads/devices" ) func SaveDeviceImagesBulk(files []*multipart.FileHeader) ([]string, error) { var imageURLs []string for i, file := range files { if file == nil { imageURLs = append(imageURLs, "") continue } // Validate file if err := validateImageFile(file); err != nil { return nil, fmt.Errorf("file %d: %w", i, err) } // Create upload directory if it doesn't exist if err := os.MkdirAll(DeviceUploadDir, 0755); err != nil { return nil, fmt.Errorf("failed to create upload directory: %v", err) } // Generate unique filename ext := strings.ToLower(filepath.Ext(file.Filename)) filename := fmt.Sprintf("%s_%d%s", uuid.New().String(), time.Now().Unix(), ext) filePath := filepath.Join(DeviceUploadDir, filename) // Save file if err := saveFile(file, filePath); err != nil { return nil, fmt.Errorf("failed to save file %d: %w", i, err) } imageURL := fmt.Sprintf("/uploads/devices/%s", filename) imageURLs = append(imageURLs, imageURL) } return imageURLs, nil } func SaveTowerImagesBulk(files []*multipart.FileHeader) ([]string, error) { var imageURLs []string for i, file := range files { if file == nil { imageURLs = append(imageURLs, "") continue } // Validate file if err := validateImageFile(file); err != nil { return nil, fmt.Errorf("file %d: %w", i, err) } // Create upload directory if it doesn't exist if err := os.MkdirAll(TowerUploadDir, 0755); err != nil { return nil, fmt.Errorf("failed to create upload directory: %v", err) } // Generate unique filename ext := strings.ToLower(filepath.Ext(file.Filename)) filename := fmt.Sprintf("%s_%d%s", uuid.New().String(), time.Now().Unix(), ext) filePath := filepath.Join(TowerUploadDir, filename) // Save file if err := saveFile(file, filePath); err != nil { return nil, fmt.Errorf("failed to save file %d: %w", i, err) } imageURL := fmt.Sprintf("/uploads/towers/%s", filename) imageURLs = append(imageURLs, imageURL) } return imageURLs, nil } // Helper functions func validateImageFile(file *multipart.FileHeader) error { // Validate file size if file.Size > MaxFileSize { return fmt.Errorf("file size exceeds 5MB limit") } // Validate file type allowedTypes := []string{".jpg", ".jpeg", ".png", ".webp"} ext := strings.ToLower(filepath.Ext(file.Filename)) isAllowed := false for _, allowedType := range allowedTypes { if ext == allowedType { isAllowed = true break } } if !isAllowed { return fmt.Errorf("file type not allowed. Only jpg, jpeg, png, webp are allowed") } return nil } func DeleteDeviceImage(imageURL string) error { if imageURL == "" { return nil } // Extract filename from URL filename := filepath.Base(imageURL) filePath := filepath.Join(DeviceUploadDir, filename) // Check if file exists if _, err := os.Stat(filePath); os.IsNotExist(err) { return nil // File doesn't exist, nothing to delete } // Delete file return os.Remove(filePath) } func saveFile(file *multipart.FileHeader, filePath string) error { // Open uploaded file src, err := file.Open() if err != nil { return fmt.Errorf("failed to open uploaded file: %v", err) } defer src.Close() // Create destination file dst, err := os.Create(filePath) if err != nil { return fmt.Errorf("failed to create destination file: %v", err) } defer dst.Close() // Copy file if _, err := io.Copy(dst, src); err != nil { return fmt.Errorf("failed to copy file: %v", err) } return nil } // SaveTowerImage saves uploaded image and returns the URL func SaveTowerImage(file *multipart.FileHeader) (string, error) { // Validate file size if file.Size > MaxFileSize { return "", fmt.Errorf("file size exceeds 5MB limit") } // Validate file type allowedTypes := []string{".jpg", ".jpeg", ".png", ".webp"} ext := strings.ToLower(filepath.Ext(file.Filename)) isAllowed := false for _, allowedType := range allowedTypes { if ext == allowedType { isAllowed = true break } } if !isAllowed { return "", fmt.Errorf("file type not allowed. Only jpg, jpeg, png, webp are allowed") } // Create upload directory if it doesn't exist if err := os.MkdirAll(TowerUploadDir, 0755); err != nil { return "", fmt.Errorf("failed to create upload directory: %v", err) } // Generate unique filename filename := fmt.Sprintf("%s_%d%s", uuid.New().String(), time.Now().Unix(), ext) filePath := filepath.Join(TowerUploadDir, filename) // Open uploaded file src, err := file.Open() if err != nil { return "", fmt.Errorf("failed to open uploaded file: %v", err) } defer src.Close() // Create destination file dst, err := os.Create(filePath) if err != nil { return "", fmt.Errorf("failed to create destination file: %v", err) } defer dst.Close() // Copy file if _, err := io.Copy(dst, src); err != nil { return "", fmt.Errorf("failed to copy file: %v", err) } // Return URL (adjust based on your server setup) return fmt.Sprintf("/uploads/towers/%s", filename), nil } // DeleteTowerImage deletes an image file func DeleteTowerImage(imageURL string) error { if imageURL == "" { return nil } // Extract filename from URL filename := filepath.Base(imageURL) filePath := filepath.Join(TowerUploadDir, filename) // Check if file exists if _, err := os.Stat(filePath); os.IsNotExist(err) { return nil // File doesn't exist, nothing to delete } // Delete file return os.Remove(filePath) }