finyx_data_ai/app/utils/file_handler.py
2026-01-11 07:48:19 +08:00

103 lines
3.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
文件处理工具
"""
import os
import shutil
from pathlib import Path
from typing import Optional
from fastapi import UploadFile
from app.core.config import settings
from app.core.exceptions import FileUploadException
from app.utils.logger import logger
def validate_file_extension(filename: str) -> bool:
"""验证文件扩展名"""
ext = Path(filename).suffix.lower()
return ext in settings.allowed_extensions
def validate_file_size(file_size: int) -> bool:
"""验证文件大小"""
return file_size <= settings.MAX_UPLOAD_SIZE
async def save_upload_file(file: UploadFile, project_id: str, subdir: Optional[str] = None) -> str:
"""
保存上传的文件
Args:
file: 上传的文件
project_id: 项目ID
subdir: 子目录(可选)
Returns:
保存的文件路径
"""
# 验证文件扩展名
if not validate_file_extension(file.filename):
raise FileUploadException(
f"不支持的文件类型。支持的类型: {', '.join(settings.allowed_extensions)}"
)
# 创建保存目录
save_dir = Path(settings.UPLOAD_DIR) / project_id
if subdir:
save_dir = save_dir / subdir
save_dir.mkdir(parents=True, exist_ok=True)
# 保存文件
file_path = save_dir / file.filename
try:
with open(file_path, "wb") as f:
content = await file.read()
# 验证文件大小
if not validate_file_size(len(content)):
raise FileUploadException(
f"文件大小超过限制(最大 {settings.MAX_UPLOAD_SIZE / 1024 / 1024:.0f}MB"
)
f.write(content)
logger.info(f"文件保存成功: {file_path}")
return str(file_path)
except Exception as e:
logger.error(f"文件保存失败: {str(e)}")
raise FileUploadException(f"文件保存失败: {str(e)}")
def cleanup_temp_file(file_path: str) -> None:
"""清理临时文件"""
try:
if os.path.exists(file_path):
os.remove(file_path)
logger.info(f"临时文件已删除: {file_path}")
except Exception as e:
logger.warning(f"删除临时文件失败: {file_path}, 错误: {str(e)}")
def cleanup_temp_directory(dir_path: str) -> None:
"""清理临时目录"""
try:
if os.path.exists(dir_path):
shutil.rmtree(dir_path)
logger.info(f"临时目录已删除: {dir_path}")
except Exception as e:
logger.warning(f"删除临时目录失败: {dir_path}, 错误: {str(e)}")
def detect_file_type(filename: str) -> str:
"""根据文件扩展名检测文件类型"""
ext = Path(filename).suffix.lower()
if ext in [".xlsx", ".xls"]:
return "excel"
elif ext in [".docx", ".doc"]:
return "word"
elif ext == ".pdf":
return "pdf"
elif ext == ".csv":
return "csv"
else:
raise FileUploadException(f"不支持的文件类型: {ext}")