from __future__ import annotations import re from pathlib import Path from uuid import uuid4 from PIL import Image, ImageDraw from pillow_heif import register_heif_opener from werkzeug.datastructures import FileStorage from werkzeug.utils import secure_filename register_heif_opener() def allowed_file(filename: str, allowed_extensions: set[str]) -> bool: return '.' in filename and filename.rsplit('.', 1)[1].lower() in allowed_extensions def _apply_image_ops(image: Image.Image, rotate: int = 0, crop_box: tuple[int, int, int, int] | None = None, scale_percent: int = 100) -> Image.Image: if image.mode not in ('RGB', 'RGBA'): image = image.convert('RGB') if rotate: image = image.rotate(-rotate, expand=True) if crop_box: x, y, w, h = crop_box if w > 0 and h > 0: image = image.crop((x, y, x + w, y + h)) if scale_percent and scale_percent != 100: width = max(1, int(image.width * (scale_percent / 100))) height = max(1, int(image.height * (scale_percent / 100))) image = image.resize((width, height)) return image def _pdf_placeholder(preview_path: Path, original_name: str) -> None: image = Image.new('RGB', (800, 1100), color='white') draw = ImageDraw.Draw(image) draw.text((40, 40), f'PDF preview\n{original_name}', fill='black') image.save(preview_path, 'WEBP', quality=80) def save_document(file: FileStorage, upload_dir: Path, preview_dir: Path, rotate: int = 0, crop_box: tuple[int, int, int, int] | None = None, scale_percent: int = 100) -> tuple[str, str]: upload_dir.mkdir(parents=True, exist_ok=True) preview_dir.mkdir(parents=True, exist_ok=True) original_name = secure_filename(file.filename or 'document') extension = original_name.rsplit('.', 1)[1].lower() if '.' in original_name else 'bin' stem = re.sub(r'[^a-zA-Z0-9_-]+', '-', Path(original_name).stem).strip('-') or 'document' unique_name = f'{stem}-{uuid4().hex}.{extension}' saved_path = upload_dir / unique_name file.save(saved_path) preview_name = f'{stem}-{uuid4().hex}.webp' preview_path = preview_dir / preview_name if extension in {'jpg', 'jpeg', 'png', 'heic'}: image = Image.open(saved_path) image = _apply_image_ops(image, rotate=rotate, crop_box=crop_box, scale_percent=scale_percent) image.save(preview_path, 'WEBP', quality=80) elif extension == 'pdf': _pdf_placeholder(preview_path, original_name) else: preview_name = '' return unique_name, preview_name