initial
This commit is contained in:
78
backend/services/image_service.py
Normal file
78
backend/services/image_service.py
Normal file
@@ -0,0 +1,78 @@
|
||||
import os
|
||||
import uuid
|
||||
from werkzeug.utils import secure_filename
|
||||
from PIL import Image
|
||||
|
||||
|
||||
def allowed_file(filename, allowed_extensions):
|
||||
"""Check if file has allowed extension"""
|
||||
return '.' in filename and \
|
||||
filename.rsplit('.', 1)[1].lower() in allowed_extensions
|
||||
|
||||
|
||||
def save_image(file, upload_folder, allowed_extensions):
|
||||
"""
|
||||
Save uploaded image file with validation
|
||||
|
||||
Args:
|
||||
file: FileStorage object from Flask request
|
||||
upload_folder: Directory to save images
|
||||
allowed_extensions: Set of allowed file extensions
|
||||
|
||||
Returns:
|
||||
str: Relative path to saved image, or None if validation fails
|
||||
|
||||
Raises:
|
||||
ValueError: If file validation fails
|
||||
"""
|
||||
if not file or file.filename == '':
|
||||
raise ValueError("No file provided")
|
||||
|
||||
if not allowed_file(file.filename, allowed_extensions):
|
||||
raise ValueError(f"File type not allowed. Allowed types: {', '.join(allowed_extensions)}")
|
||||
|
||||
# Verify it's actually an image
|
||||
try:
|
||||
img = Image.open(file.stream)
|
||||
img.verify()
|
||||
file.stream.seek(0) # Reset stream after verification
|
||||
except Exception as e:
|
||||
raise ValueError(f"Invalid image file: {str(e)}")
|
||||
|
||||
# Generate unique filename
|
||||
original_filename = secure_filename(file.filename)
|
||||
extension = original_filename.rsplit('.', 1)[1].lower()
|
||||
unique_filename = f"{uuid.uuid4()}.{extension}"
|
||||
|
||||
# Ensure upload folder exists
|
||||
os.makedirs(upload_folder, exist_ok=True)
|
||||
|
||||
# Save file
|
||||
filepath = os.path.join(upload_folder, unique_filename)
|
||||
file.save(filepath)
|
||||
|
||||
# Return relative path (for storing in database)
|
||||
return f"/static/images/{unique_filename}"
|
||||
|
||||
|
||||
def delete_image(image_path, base_folder):
|
||||
"""
|
||||
Delete an image file
|
||||
|
||||
Args:
|
||||
image_path: Relative path to image (e.g., /static/images/abc123.jpg)
|
||||
base_folder: Base folder for the application
|
||||
"""
|
||||
if not image_path:
|
||||
return
|
||||
|
||||
# Remove leading slash and construct full path
|
||||
relative_path = image_path.lstrip('/')
|
||||
full_path = os.path.join(base_folder, relative_path)
|
||||
|
||||
try:
|
||||
if os.path.exists(full_path):
|
||||
os.remove(full_path)
|
||||
except Exception as e:
|
||||
# Log error but don't fail the operation
|
||||
print(f"Error deleting image {full_path}: {str(e)}")
|
||||
Reference in New Issue
Block a user