72 lines
2.3 KiB
Python
72 lines
2.3 KiB
Python
"""
|
||
Router: zdjęcia profilowe użytkowników.
|
||
Ścieżka na dysku: {files_base_dir}/user_files/profile/<uuid>.ext
|
||
|
||
Endpointy:
|
||
POST /user_files/profile/upload – przesyłanie zdjęcia profilowego
|
||
GET /user_files/profile/file/{filename} – pobieranie zdjęcia profilowego
|
||
DELETE /user_files/profile/file/{filename} – usuwanie zdjęcia profilowego
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
import mimetypes
|
||
|
||
from fastapi import APIRouter, Depends, HTTPException, UploadFile, File
|
||
from fastapi.responses import FileResponse
|
||
|
||
from ..auth import require_api_key
|
||
from ..storage import save_file, get_stored_file_path, delete_stored_file
|
||
|
||
router = APIRouter(prefix="/user_files/profile", tags=["user_profile"])
|
||
|
||
_SUBFOLDER = "user_files/profile"
|
||
|
||
# Dla zdjęć profilowych akceptujemy tylko obrazy
|
||
_ALLOWED_IMAGE_TYPES = frozenset(
|
||
{"image/jpeg", "image/png", "image/gif", "image/webp"}
|
||
)
|
||
|
||
|
||
@router.post("/upload", summary="Prześlij zdjęcie profilowe")
|
||
async def upload_profile_picture(
|
||
file: UploadFile = File(...),
|
||
_key: str = Depends(require_api_key),
|
||
):
|
||
content_type = (file.content_type or "").split(";")[0].strip()
|
||
if content_type not in _ALLOWED_IMAGE_TYPES:
|
||
raise HTTPException(
|
||
status_code=415,
|
||
detail=f"Zdjęcie profilowe musi być obrazem (JPEG/PNG/GIF/WEBP). Otrzymano: {content_type}",
|
||
)
|
||
result = await save_file(
|
||
file,
|
||
_SUBFOLDER,
|
||
convert_image_to_webp=True,
|
||
image_max_side=512,
|
||
image_quality=82,
|
||
)
|
||
return {"success": True, "data": result}
|
||
|
||
|
||
@router.get("/file/{filename}", summary="Pobierz zdjęcie profilowe")
|
||
async def serve_profile_picture(
|
||
filename: str,
|
||
_key: str = Depends(require_api_key),
|
||
):
|
||
file_path = get_stored_file_path(_SUBFOLDER, filename)
|
||
mime = mimetypes.guess_type(str(file_path))[0] or "image/jpeg"
|
||
return FileResponse(
|
||
path=str(file_path),
|
||
media_type=mime,
|
||
headers={"Content-Disposition": f'inline; filename="{filename}"'},
|
||
)
|
||
|
||
|
||
@router.delete("/file/{filename}", summary="Usuń zdjęcie profilowe")
|
||
async def delete_profile_picture(
|
||
filename: str,
|
||
_key: str = Depends(require_api_key),
|
||
):
|
||
deleted = delete_stored_file(_SUBFOLDER, filename)
|
||
return {"success": deleted}
|