# -*- coding = utf-8 -*- # @Time : 2025/2/13 下午4:50 # @File : routes.py # @Software : PyCharm # @Author : xingc # @Desc : import hashlib import logging import os from io import BytesIO from typing import Literal from fastapi import APIRouter, UploadFile, File, status, HTTPException, Depends from PIL import Image from config import settings from . import schema from core.base.schema import BaseResponse logger = logging.getLogger(__name__) file_router = APIRouter(prefix='/file', tags=['文件存储模块']) @file_router.post('/{upload_type}/upload', response_model=BaseResponse[schema.FileOut]) async def upload_file( upload_type: Literal['card', 'chat', 'avatar'], file: UploadFile = File(...) ): # 验证文件类型 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 = [settings.UPLOADED_FILES_DIR, upload_type.lower()] if upload_type.lower() != 'card': dirname_args.append('test') save_path = os.path.join(*dirname_args) save_file_path = os.path.join(*dirname_args, file_name) if os.path.exists(save_file_path) is False: # 创建目录 os.makedirs(save_path, 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': os.path.getsize(save_path), 'hash': file_hash, 'url': save_file_path } 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' )