79 lines
2.3 KiB
Python
79 lines
2.3 KiB
Python
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)}")
|