""" 文件工具函数 提供统一的文件删除功能,自动处理缩略图同步删除 """ import os from pathlib import Path from app.config import get_settings settings = get_settings() # 文件系统路径(从配置读取) UPLOAD_DIR = Path(settings.UPLOAD_DIR) THUMBNAIL_DIR = UPLOAD_DIR / "thumbnails" # URL 路径 STORAGE_URL = "/storage/admin/images" THUMBNAIL_URL = f"{STORAGE_URL}/thumbnails" def cleanup_file(file_path: str | Path) -> bool: """ 删除文件并同步删除对应的缩略图 Args: file_path: 文件路径(相对 /uploads 的路径、/storage/admin/images/ 格式或绝对路径) Returns: bool: 是否成功删除原文件 """ if not file_path: return False # 统一处理为 Path 对象 if isinstance(file_path, str): # 处理新的存储路径格式 /storage/admin/images/... if file_path.startswith("/storage/admin/images/"): # 提取相对路径部分 relative_path = file_path[len("/storage/admin/images/"):] full_path = UPLOAD_DIR / relative_path else: # 移除开头的 / 并构建完整路径(兼容旧格式) relative_path = file_path.lstrip("/") full_path = UPLOAD_DIR / relative_path else: full_path = file_path # 删除原文件 deleted = False try: if full_path.exists(): full_path.unlink() deleted = True print(f"[cleanup] 已删除文件: {full_path}") except Exception as e: print(f"[cleanup] 删除文件失败 {full_path}: {e}") # 同步删除缩略图 # 缩略图与原图同名,但扩展名统一为 .jpg,存放在 /uploads/thumbnails/ try: thumbnail_name = f"{full_path.stem}.jpg" thumb_path = THUMBNAIL_DIR / thumbnail_name if thumb_path.exists(): thumb_path.unlink() print(f"[cleanup] 已删除缩略图: {thumb_path}") except Exception as e: print(f"[cleanup] 删除缩略图失败: {e}") return deleted def cleanup_file_by_path(relative_path: str) -> bool: """ 根据相对路径删除文件及其缩略图 Args: relative_path: 相对于 /uploads 的路径,如 "20250420_xxx.jpg" 或者完整的存储路径如 "/storage/admin/images/xxx.jpg" Returns: bool: 是否成功删除原文件 """ if not relative_path: return False # 排除外部 URL if relative_path.startswith(("http://", "https://")): print(f"[cleanup] 跳过外部 URL: {relative_path}") return False # 处理新的存储路径格式 /storage/admin/images/... if relative_path.startswith("/storage/admin/images/"): # 提取相对路径部分 rel_path = relative_path[len("/storage/admin/images/"):] full_path = UPLOAD_DIR / rel_path else: # 处理可能包含开头 / 的路径(兼容旧格式) rel_path = relative_path.lstrip("/") full_path = UPLOAD_DIR / rel_path return cleanup_file(full_path)