diff --git a/digital-avatar-app/backend/routers/avatars.py b/digital-avatar-app/backend/routers/avatars.py index 956a56d..42a1e49 100644 --- a/digital-avatar-app/backend/routers/avatars.py +++ b/digital-avatar-app/backend/routers/avatars.py @@ -1,7 +1,11 @@ -from fastapi import APIRouter, Depends, Body, Header +from fastapi import APIRouter, Depends, Body, Header, UploadFile, File from sqlalchemy.orm import Session +import os +import uuid +import mimetypes from database import get_db +from routers.knowledge import UPLOAD_DIR from models import Avatar, KnowledgeDoc, KnowledgeChunk, QAPair, Authorization, User from responses import ok, fail @@ -93,3 +97,41 @@ def delete_avatar(avatar_id: str, db: Session = Depends(get_db)): db.delete(a) db.commit() return ok({"success": True}) + + +@router.post("/avatar/{avatar_id}/photo") +async def upload_avatar_photo( + avatar_id: str, + file: UploadFile = File(...), + db: Session = Depends(get_db), +): + """上传数字分身头像""" + a = db.query(Avatar).filter(Avatar.id == avatar_id).first() + if not a: + return fail("分身不存在", 404) + + # 验证文件类型 + if not file.content_type or not file.content_type.startswith("image/"): + return fail("仅支持图片文件", 400) + + file_bytes = await file.read() + if len(file_bytes) > 5 * 1024 * 1024: + return fail("头像文件不能超过5MB", 400) + + # 保存到 uploads 目录 + ext = mimetypes.guess_extension(file.content_type) or ".jpg" + filename = f"avatar-{uuid.uuid4().hex}{ext}" + avatar_dir = os.path.join(UPLOAD_DIR, avatar_id) + os.makedirs(avatar_dir, exist_ok=True) + file_path = os.path.join(avatar_dir, filename) + + with open(file_path, "wb") as f: + f.write(file_bytes) + + # 更新数据库 + photo_url = f"/api/files/{avatar_id}/{filename}" + a.photo_url = photo_url + db.commit() + db.refresh(a) + + return ok(a.to_dict())