Initial project commit
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
import uuid
|
||||
from pathlib import Path
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request, UploadFile, status
|
||||
|
||||
from app.core.deps import get_current_active_user
|
||||
from app.core.rate_limit import RateLimiter
|
||||
from app.core.storage import S3StorageBackend
|
||||
from app.models.user import User
|
||||
from app.schemas.upload import PresignedUrlRequest, PresignedUrlResponse, UploadResponse
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
ALLOWED_TYPES = {"image/jpeg", "image/png", "image/gif", "image/webp"}
|
||||
MAX_SIZE = 10 * 1024 * 1024 # 10MB
|
||||
|
||||
|
||||
@router.post(
|
||||
"/image",
|
||||
response_model=UploadResponse,
|
||||
dependencies=[Depends(RateLimiter(times=20, seconds=60))],
|
||||
)
|
||||
async def upload_image(
|
||||
request: Request,
|
||||
file: UploadFile,
|
||||
current_user: User = Depends(get_current_active_user),
|
||||
):
|
||||
if file.content_type not in ALLOWED_TYPES:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail=f"Unsupported file type: {file.content_type}",
|
||||
)
|
||||
|
||||
data = await file.read()
|
||||
if len(data) > MAX_SIZE:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE,
|
||||
detail="File too large, max 10MB",
|
||||
)
|
||||
|
||||
storage = request.app.state.storage
|
||||
url = storage.upload(data, file.filename or "image.jpg", file.content_type or "")
|
||||
|
||||
return UploadResponse(url=url, filename=file.filename or "image.jpg")
|
||||
|
||||
|
||||
@router.post("/presigned", response_model=PresignedUrlResponse)
|
||||
async def get_presigned_upload_url(
|
||||
request: Request,
|
||||
payload: PresignedUrlRequest,
|
||||
current_user: User = Depends(get_current_active_user),
|
||||
):
|
||||
storage = request.app.state.storage
|
||||
if not isinstance(storage, S3StorageBackend):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Presigned URLs only available with S3 storage backend",
|
||||
)
|
||||
|
||||
ext = Path(payload.filename).suffix or ".jpg"
|
||||
file_key = f"images/{uuid.uuid4().hex}{ext}"
|
||||
upload_url = storage.generate_presigned_url(
|
||||
file_key, content_type=payload.content_type
|
||||
)
|
||||
public_url = storage._get_url(file_key)
|
||||
|
||||
return PresignedUrlResponse(
|
||||
upload_url=upload_url,
|
||||
file_key=file_key,
|
||||
public_url=public_url,
|
||||
)
|
||||
Reference in New Issue
Block a user