test_zadanie_S3/app/main.py
2024-03-23 14:09:12 +03:00

82 lines
2.6 KiB
Python

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