ForcePilot/backend/package/yuxi/channel/utils/file_service.py
Kris 3b487fae57 feat(channel/utils): 新增工具模块与文件服务类
新增了通用工具包,包含文件操作工具、延迟加载工具类与函数,以及文件服务类,提供文件分类、安全命名与上传保存功能
2026-05-21 10:33:11 +08:00

42 lines
1.4 KiB
Python

from __future__ import annotations
import hashlib
import os
import re
from pathlib import Path
IMAGE_EXTENSIONS = {".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp", ".svg"}
VIDEO_EXTENSIONS = {".mp4", ".mov", ".avi", ".mkv", ".webm", ".flv", ".wmv"}
ALLOWED_EXTENSIONS = IMAGE_EXTENSIONS | VIDEO_EXTENSIONS | {".pdf", ".txt", ".json", ".zip", ".rar"}
_DEFAULT_MAX_FILE_BYTES = 50 * 1024 * 1024
class FileService:
def __init__(self, storage_dir: str | Path, max_file_bytes: int = _DEFAULT_MAX_FILE_BYTES):
self.storage_dir = Path(storage_dir)
self.storage_dir.mkdir(parents=True, exist_ok=True)
self.max_file_bytes = max_file_bytes
def classify(self, filename: str) -> str:
ext = os.path.splitext(filename)[1].lower()
if ext in IMAGE_EXTENSIONS:
return "image"
if ext in VIDEO_EXTENSIONS:
return "video"
return "file"
def generate_safe_name(self, original_name: str) -> str:
name = self._sanitize_filename(original_name)
h = hashlib.sha256(name.encode()).hexdigest()[:12]
ext = os.path.splitext(original_name)[1].lower()
return f"{h}_{name}"
async def save_upload(self, content: bytes, safe_name: str) -> Path:
dest = self.storage_dir / safe_name
dest.write_bytes(content)
return dest
@staticmethod
def _sanitize_filename(filename: str) -> str:
return re.sub(r"[^\w.\-]", "_", filename)