79 lines
2.6 KiB
Python
79 lines
2.6 KiB
Python
# -*- coding = utf-8 -*-
|
|
# @Time : 2025/2/13 下午4:50
|
|
# @File : routes.py
|
|
# @Software : PyCharm
|
|
# @Author : xingc
|
|
# @Desc :
|
|
import hashlib
|
|
import logging
|
|
from io import BytesIO
|
|
from pathlib import Path
|
|
from typing import Literal
|
|
from urllib.parse import urljoin
|
|
|
|
from fastapi import APIRouter, UploadFile, File, status, HTTPException, Depends
|
|
from PIL import Image
|
|
|
|
from config import settings
|
|
from core.base.schema import BaseResponse
|
|
from core.routers.auth.schema import LoginUser
|
|
from core.routers.auth.services import get_current_user
|
|
|
|
from . import schema
|
|
|
|
logger = logging.getLogger(__name__)
|
|
file_router = APIRouter(prefix='/file', tags=['文件存储模块'])
|
|
|
|
|
|
@file_router.post('/{upload_type}/upload', summary='图片上传', response_model=BaseResponse[schema.FileOut])
|
|
async def upload_file(
|
|
upload_type: Literal['card', 'chat', 'avatar'],
|
|
file: UploadFile = File(...),
|
|
login_user: LoginUser = Depends(get_current_user)
|
|
):
|
|
# 验证文件类型
|
|
if file.content_type not in settings.UPLOADED_ALLOWED_MIME_TYPES:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_415_UNSUPPORTED_MEDIA_TYPE,
|
|
detail=f'Unsupported media type: {file.content_type}'
|
|
)
|
|
|
|
# 验证文件大小
|
|
if file.size > settings.UPLOADED_MAX_FILE_SIZE:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE,
|
|
detail=f'File exceeds maximum size'
|
|
)
|
|
|
|
try:
|
|
file_chunks = await file.read()
|
|
file_hash = hashlib.sha256(file_chunks).hexdigest()
|
|
file_name = f'{file_hash}.jpg'
|
|
dirname_args = [upload_type.lower(), str(login_user.user_id), file_name]
|
|
|
|
save_file_path: Path = settings.UPLOADED_FILES_DIR.joinpath(*dirname_args)
|
|
if save_file_path.exists() is False:
|
|
# 创建目录
|
|
save_file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
|
|
img = Image.open(BytesIO(file_chunks))
|
|
img = img.convert("RGB")
|
|
img.save(save_file_path, format="JPEG")
|
|
|
|
file_info = {
|
|
'filename': file_name,
|
|
'content_type': file.content_type,
|
|
'size': file.size,
|
|
'hash': file_hash,
|
|
'url': urljoin(settings.ASSETS_BASE_URL, '/'.join([settings.UPLOADED_FILES_DIR.name, *dirname_args])),
|
|
}
|
|
return {'data': file_info}
|
|
|
|
except Exception as e:
|
|
logger.error(f'Upload failed: {str(e)}')
|
|
logger.exception(e)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f'File upload failed'
|
|
)
|