Files
FilesReadSystem/backend/app/services/file_service.py
2026-03-30 21:24:13 +08:00

139 lines
3.4 KiB
Python

"""
文件服务模块 - 处理文件存储和读取
"""
import os
import shutil
import logging
from pathlib import Path
from datetime import datetime
from typing import Optional
import uuid
from app.config import settings
logger = logging.getLogger(__name__)
class FileService:
"""文件服务类,负责文件的存储、读取和管理"""
def __init__(self):
self.upload_dir = Path(settings.UPLOAD_DIR)
self._ensure_upload_dir()
logger.info(f"FileService 初始化,上传目录: {self.upload_dir}")
def _ensure_upload_dir(self):
"""确保上传目录存在"""
self.upload_dir.mkdir(parents=True, exist_ok=True)
def save_uploaded_file(
self,
file_content: bytes,
filename: str,
subfolder: Optional[str] = None
) -> str:
"""
保存上传的文件
Args:
file_content: 文件内容字节
filename: 原始文件名
subfolder: 可选的子文件夹名称
Returns:
str: 保存后的文件路径
"""
# 生成唯一文件名,避免覆盖
file_ext = Path(filename).suffix
unique_name = f"{uuid.uuid4().hex}{file_ext}"
# 确定保存路径
if subfolder:
save_dir = self.upload_dir / subfolder
save_dir.mkdir(parents=True, exist_ok=True)
else:
save_dir = self.upload_dir
file_path = save_dir / unique_name
# 写入文件
with open(file_path, 'wb') as f:
f.write(file_content)
file_size = len(file_content)
logger.info(f"文件已保存: {filename} -> {file_path} ({file_size} bytes)")
return str(file_path)
def read_file(self, file_path: str) -> bytes:
"""
读取文件内容
Args:
file_path: 文件路径
Returns:
bytes: 文件内容
"""
with open(file_path, 'rb') as f:
return f.read()
def delete_file(self, file_path: str) -> bool:
"""
删除文件
Args:
file_path: 文件路径
Returns:
bool: 是否删除成功
"""
try:
file = Path(file_path)
if file.exists():
file.unlink()
return True
return False
except Exception:
return False
def get_file_info(self, file_path: str) -> dict:
"""
获取文件信息
Args:
file_path: 文件路径
Returns:
dict: 文件信息
"""
file = Path(file_path)
if not file.exists():
return {}
stat = file.stat()
return {
"filename": file.name,
"filepath": str(file),
"size": stat.st_size,
"created": datetime.fromtimestamp(stat.st_ctime).isoformat(),
"modified": datetime.fromtimestamp(stat.st_mtime).isoformat(),
"extension": file.suffix.lower()
}
def get_file_size(self, file_path: str) -> int:
"""
获取文件大小(字节)
Args:
file_path: 文件路径
Returns:
int: 文件大小,文件不存在返回 0
"""
file = Path(file_path)
return file.stat().st_size if file.exists() else 0
# 全局单例
file_service = FileService()