From 70eb6f5a0b0646d656f148b583102ed484b81d37 Mon Sep 17 00:00:00 2001 From: cest-la-v <22951622+cest-la-v@users.noreply.github.com> Date: Thu, 23 Apr 2026 22:31:24 +0800 Subject: [PATCH] fix(files-api): make GET /files/{directory_type} recursive Replace os.scandir (top-level only) with os.walk so nested subfolders are included. Returns relative paths (e.g. '2025-01/foo.png') which the frontend's getMediaUrl already handles via subfolder param splitting. Hidden files and hidden directories (starting with '.') are pruned. Applies to all three directory types: input, output, temp. --- api_server/routes/internal/internal_routes.py | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/api_server/routes/internal/internal_routes.py b/api_server/routes/internal/internal_routes.py index 1477afa01..6399830d6 100644 --- a/api_server/routes/internal/internal_routes.py +++ b/api_server/routes/internal/internal_routes.py @@ -59,15 +59,22 @@ class InternalRoutes: directory = get_directory_by_type(directory_type) - def is_visible_file(entry: os.DirEntry) -> bool: - """Filter out hidden files (e.g., .DS_Store on macOS).""" - return entry.is_file() and not entry.name.startswith('.') + def walk_visible_files(base: str): + """Recursively yield (rel_path, mtime) for all non-hidden files.""" + for dirpath, dirnames, filenames in os.walk(base): + dirnames[:] = [d for d in dirnames if not d.startswith('.')] + for f in filenames: + if f.startswith('.'): + continue + full = os.path.join(dirpath, f) + rel = os.path.relpath(full, base).replace('\\', '/') + try: + yield rel, os.stat(full).st_mtime + except OSError: + continue - sorted_files = sorted( - (entry for entry in os.scandir(directory) if is_visible_file(entry)), - key=lambda entry: -entry.stat().st_mtime - ) - return web.json_response([f"{entry.name} [{directory_type}]" for entry in sorted_files], status=200) + sorted_files = sorted(walk_visible_files(directory), key=lambda x: -x[1]) + return web.json_response([path for path, _ in sorted_files], status=200) def get_app(self):