82 lines
2.6 KiB
Python
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
|