import os import base64 from datetime import datetime from typing import Optional import uuid from PIL import Image import io UPLOAD_DIR = "/app/uploads" def ensure_upload_dir(): """업로드 디렉토리 생성""" if not os.path.exists(UPLOAD_DIR): os.makedirs(UPLOAD_DIR) def save_base64_image(base64_string: str, prefix: str = "image") -> Optional[str]: """Base64 이미지를 파일로 저장하고 경로 반환""" try: ensure_upload_dir() # Base64 헤더 제거 if "," in base64_string: base64_string = base64_string.split(",")[1] # 디코딩 image_data = base64.b64decode(base64_string) # 이미지 검증 및 형식 확인 image = Image.open(io.BytesIO(image_data)) # iPhone의 .mpo 파일이나 기타 형식을 JPEG로 강제 변환 # RGB 모드로 변환 (RGBA, P 모드 등을 처리) if image.mode in ('RGBA', 'LA', 'P'): # 투명도가 있는 이미지는 흰 배경과 합성 background = Image.new('RGB', image.size, (255, 255, 255)) if image.mode == 'P': image = image.convert('RGBA') background.paste(image, mask=image.split()[-1] if image.mode == 'RGBA' else None) image = background elif image.mode != 'RGB': image = image.convert('RGB') # 파일명 생성 (prefix 포함) filename = f"{prefix}_{datetime.now().strftime('%Y%m%d%H%M%S')}_{uuid.uuid4().hex[:8]}.jpg" filepath = os.path.join(UPLOAD_DIR, filename) # 이미지 저장 (최대 크기 제한) max_size = (1920, 1920) image.thumbnail(max_size, Image.Resampling.LANCZOS) # 항상 JPEG로 저장 image.save(filepath, 'JPEG', quality=85, optimize=True) # 웹 경로 반환 return f"/uploads/{filename}" except Exception as e: print(f"이미지 저장 실패: {e}") return None def delete_file(filepath: str): """파일 삭제""" try: if filepath and filepath.startswith("/uploads/"): filename = filepath.replace("/uploads/", "") full_path = os.path.join(UPLOAD_DIR, filename) if os.path.exists(full_path): os.remove(full_path) except Exception as e: print(f"파일 삭제 실패: {e}")