SumakaClone / backend /app /utils /file_validation.py
raghava0450's picture
Deploy SumakaClone Space configuration
92d8b0d verified
Raw
History Blame Contribute Delete
1.58 kB
from __future__ import annotations
import hashlib
import io
from dataclasses import dataclass
from PIL import Image, UnidentifiedImageError
FORMAT_MIME_MAP = {
"PNG": "image/png",
"JPEG": "image/jpeg",
"WEBP": "image/webp",
}
@dataclass(slots=True)
class ImageUploadInfo:
width: int
height: int
mime_type: str
sha256: str
size_bytes: int
format_name: str
class FileValidationError(ValueError):
"""Raised when an uploaded image is invalid."""
def validate_image_bytes(data: bytes, max_size_mb: int) -> ImageUploadInfo:
size_bytes = len(data)
max_size_bytes = max_size_mb * 1024 * 1024
if size_bytes == 0:
raise FileValidationError("Uploaded image is empty.")
if size_bytes > max_size_bytes:
raise FileValidationError(f"Image exceeds the {max_size_mb} MB upload limit.")
try:
image = Image.open(io.BytesIO(data))
image.verify()
image = Image.open(io.BytesIO(data))
except (UnidentifiedImageError, OSError) as exc:
raise FileValidationError("Unsupported or corrupted image file.") from exc
format_name = (image.format or "").upper()
mime_type = FORMAT_MIME_MAP.get(format_name)
if mime_type is None:
raise FileValidationError("Only PNG, JPEG, and WEBP images are supported.")
sha256 = hashlib.sha256(data).hexdigest()
return ImageUploadInfo(
width=image.width,
height=image.height,
mime_type=mime_type,
sha256=sha256,
size_bytes=size_bytes,
format_name=format_name.lower(),
)