新增头像接口:POST /profiles/me/avatar 上传、DELETE /profiles/me/avatar 删除
This commit is contained in:
@@ -12,6 +12,7 @@ from app.config import settings
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
ALLOWED_FORMATS = {"JPEG": "jpg", "PNG": "png", "WEBP": "webp"}
|
||||
AVATAR_MAX_EDGE = 512
|
||||
|
||||
|
||||
def _process_image(raw: bytes) -> tuple[bytes, str, bytes]:
|
||||
@@ -105,3 +106,38 @@ async def delete_files(paths: list[str]) -> None:
|
||||
logger.exception("删除图片失败:%s", relative_path)
|
||||
|
||||
await asyncio.to_thread(remove)
|
||||
|
||||
|
||||
async def save_avatar(file: UploadFile, user_id: uuid.UUID) -> str:
|
||||
raw = await file.read(settings.max_upload_bytes + 1)
|
||||
if not raw:
|
||||
raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="图片不能为空")
|
||||
if len(raw) > settings.max_upload_bytes:
|
||||
raise HTTPException(status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE, detail="图片文件过大")
|
||||
|
||||
def process() -> str:
|
||||
Image.MAX_IMAGE_PIXELS = settings.max_image_pixels
|
||||
try:
|
||||
with Image.open(io.BytesIO(raw)) as source:
|
||||
if source.format not in ALLOWED_FORMATS:
|
||||
raise ValueError("仅支持 JPEG、PNG 和 WebP 图片")
|
||||
source = source.convert("RGB")
|
||||
source.thumbnail(
|
||||
(AVATAR_MAX_EDGE, AVATAR_MAX_EDGE),
|
||||
Image.Resampling.LANCZOS,
|
||||
)
|
||||
relative_path = Path("avatars") / f"{user_id}.jpg"
|
||||
target = settings.upload_dir / relative_path
|
||||
target.parent.mkdir(parents=True, exist_ok=True)
|
||||
source.save(target, format="JPEG", quality=85, optimize=True)
|
||||
return relative_path.as_posix()
|
||||
except (UnidentifiedImageError, OSError, Image.DecompressionBombError, ValueError) as exc:
|
||||
raise ValueError(str(exc) or "图片内容无效") from exc
|
||||
|
||||
try:
|
||||
return await asyncio.to_thread(process)
|
||||
except ValueError as exc:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=f"图片无法处理:{exc}",
|
||||
) from exc
|
||||
|
||||
Reference in New Issue
Block a user