Initial commit: AI Interview System

This commit is contained in:
111
2026-01-23 13:57:48 +08:00
commit 95770afe21
127 changed files with 24686 additions and 0 deletions

View File

@@ -0,0 +1,97 @@
"""
文件上传接口
"""
import os
import uuid
from datetime import datetime
from fastapi import APIRouter, UploadFile, File, HTTPException, Request
from fastapi.responses import FileResponse
from loguru import logger
from app.schemas import ApiResponse
from app.config import settings
router = APIRouter()
# 上传目录
UPLOAD_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "uploads")
os.makedirs(UPLOAD_DIR, exist_ok=True)
@router.post("/upload", response_model=ApiResponse)
async def upload_file(request: Request, file: UploadFile = File(...)):
"""
上传文件并返回公开访问链接
- 接收前端上传的文件(如简历 PDF
- 保存到本地并生成公开链接
- 返回文件链接供 Coze 工作流使用
"""
try:
# 验证文件类型
if not file.filename.lower().endswith('.pdf'):
raise HTTPException(status_code=400, detail="仅支持 PDF 格式")
# 读取文件内容
content = await file.read()
# 验证文件大小(最大 10MB
if len(content) > 10 * 1024 * 1024:
raise HTTPException(status_code=400, detail="文件大小不能超过 10MB")
# 生成唯一文件名
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
unique_id = uuid.uuid4().hex[:8]
safe_filename = f"{timestamp}_{unique_id}.pdf"
# 保存文件
file_path = os.path.join(UPLOAD_DIR, safe_filename)
with open(file_path, "wb") as f:
f.write(content)
logger.info(f"File saved: {file_path}, size: {len(content)} bytes")
# 生成公开访问链接
# 从请求中获取 host
host = request.headers.get("host", "localhost:8000")
scheme = request.headers.get("x-forwarded-proto", "http")
file_url = f"{scheme}://{host}/api/files/{safe_filename}"
logger.info(f"File URL: {file_url}")
return ApiResponse(
code=0,
message="success",
data={
"fileUrl": file_url,
"fileName": file.filename,
"fileSize": len(content),
}
)
except HTTPException:
raise
except Exception as e:
logger.error(f"Upload error: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.get("/files/{filename}")
async def get_file(filename: str):
"""
获取上传的文件(供 Coze 工作流访问)
"""
# 安全检查:防止路径遍历
if ".." in filename or "/" in filename or "\\" in filename:
raise HTTPException(status_code=400, detail="Invalid filename")
file_path = os.path.join(UPLOAD_DIR, filename)
if not os.path.exists(file_path):
raise HTTPException(status_code=404, detail="File not found")
return FileResponse(
file_path,
media_type="application/pdf",
filename=filename
)