226 lines
6.4 KiB
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)
|
|
} |