NAM-APJATEL-BACKEND/utils/helper/image_uploader.go

226 lines
6.4 KiB
Go

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