File size: 2,827 Bytes
d2d7c02
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import gradio as gr
import os
import zipfile
from pathlib import Path

# The base directory that will be explored
BASE_DIR = Path(__file__).resolve().parent / "your_target_folder"

# Ensure BASE_DIR exists
BASE_DIR.mkdir(parents=True, exist_ok=True)

def resolve_path(current_rel_path: str) -> Path:
    """Secure path resolution within BASE_DIR"""
    resolved_path = (BASE_DIR / current_rel_path).resolve()
    if BASE_DIR not in resolved_path.parents and resolved_path != BASE_DIR:
        raise ValueError("Access outside base directory is not allowed.")
    return resolved_path

def list_dir(current_rel_path: str = ""):
    current_path = resolve_path(current_rel_path)

    # Parent folder navigation
    parent_rel = str(Path(current_rel_path).parent) if current_rel_path else ""
    entries = []

    if current_path != BASE_DIR:
        entries.append(("..", "⬆️ Parent Folder"))

    # List directories and files
    for item in sorted(current_path.iterdir()):
        rel_item = os.path.relpath(item, BASE_DIR)
        label = f"📁 {item.name}" if item.is_dir() else f"📄 {item.name}"
        entries.append((rel_item, label))

    return gr.update(choices=entries, value=None), f"Currently in: /{current_rel_path}"

def download_entry(selected_rel_path: str):
    selected_path = resolve_path(selected_rel_path)

    if selected_path.is_file():
        return selected_path
    elif selected_path.is_dir():
        zip_path = f"/tmp/{selected_path.name}.zip"
        with zipfile.ZipFile(zip_path, "w") as zipf:
            for root, dirs, files in os.walk(selected_path):
                for file in files:
                    abs_file = os.path.join(root, file)
                    arc_file = os.path.relpath(abs_file, selected_path)
                    zipf.write(abs_file, arc_file)
        return zip_path
    else:
        return None

with gr.Blocks() as demo:
    current_path = gr.State("")

    gr.Markdown("# 📁 Folder Browser")
    
    with gr.Row():
        folder_dropdown = gr.Dropdown(label="Select File or Folder", choices=[])
        refresh_btn = gr.Button("🔄 Refresh")
    
    status_text = gr.Textbox(label="Current Path", interactive=False)
    download_btn = gr.Button("⬇️ Download Selected")
    file_output = gr.File(label="Download Result")

    # Events
    refresh_btn.click(fn=list_dir, inputs=current_path, outputs=[folder_dropdown, status_text])
    
    folder_dropdown.change(
        fn=lambda x: (x, *list_dir(x)),  # update path, refresh list
        inputs=folder_dropdown,
        outputs=[current_path, folder_dropdown, status_text],
    )

    download_btn.click(fn=download_entry, inputs=folder_dropdown, outputs=file_output)

    # Initial trigger
    demo.load(fn=list_dir, inputs=current_path, outputs=[folder_dropdown, status_text])

demo.launch()