import uuid from fastapi import FastAPI, UploadFile from fastapi.middleware.cors import CORSMiddleware import boto3 from httpx import AsyncClient from PIL import Image, UnidentifiedImageError from io import BytesIO from app.config import settings from app.shemas import SImage from app.tasks.tasks import resize_image from app.exceptions import IncorrectFileException, BrokenFileException, UnexpectedErrorException app = FastAPI( title="Сервер загрузки изображений в S3", root_path="/api", ) origins = [] app.add_middleware( CORSMiddleware, allow_origins=origins, allow_credentials=True, allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"], allow_headers=[ "Content-Type", "Set-Cookie", "Access-Control-Allow-Headers", "Authorization", "Accept" ], ) s3 = boto3.client('s3', endpoint_url=settings.S3_ENDPOINT_URL, region_name=settings.REGION_NAME, aws_access_key_id=settings.AWS_ACCESS_KEY_ID, aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY) @app.post("/upload_image", response_model=SImage) async def upload_image(file: UploadFile, target_width: int = 250): try: content = await file.read() image = Image.open(BytesIO(content)) image_type = image.format.lower() if image_type not in ["png", "jpeg"]: raise IncorrectFileException result = resize_image.delay({"file": content}, target_width) result_data = result.get() new_image = result_data["new_image"] except UnidentifiedImageError: raise IncorrectFileException except (OSError, SyntaxError): raise BrokenFileException except Exception: raise UnexpectedErrorException object_key = str(uuid.uuid4()) + f".{image_type}" try: post = s3.generate_presigned_post(settings.BUCKET_NAME, object_key, Fields={"Content-Type": "image/webp"}, Conditions=[["eq", "$content-type", "image/webp"]]) async with AsyncClient() as ac: await ac.post(post["url"], data=post["fields"], files=[("file", (object_key, new_image))]) response = s3.generate_presigned_url('get_object', Params={'Bucket': settings.BUCKET_NAME, 'Key': object_key}, ExpiresIn=36000) return {"resized_image_link": response} except Exception: raise UnexpectedErrorException