Spaces:
Running
Running
import gradio as gr | |
import os | |
import shutil | |
# --- Configuration --- | |
INITIAL_PATH = os.getcwd() # Start in the current working directory | |
ALLOWED_EXTENSIONS_UPLOAD = None # Allow all file types for upload initially, or set a list like ['.txt', '.pdf'] | |
ALLOWED_EXTENSIONS_DOWNLOAD = None # Allow all for download, or restrict if needed | |
# --- Helper Functions --- | |
def list_files_and_folders(path): | |
"""Lists files and folders in a given directory.""" | |
try: | |
items = os.listdir(path) | |
files = [] | |
folders = [] | |
for item in items: | |
item_path = os.path.join(path, item) | |
if os.path.isfile(item_path): | |
files.append(item) | |
elif os.path.isdir(item_path): | |
folders.append(item) | |
return folders, files, path, None # Return folders, files, current path, and no error | |
except Exception as e: | |
return [], [], path, str(e) # Return empty lists and error message | |
def change_directory(path, current_path, direction): | |
"""Changes the current directory (up or into a folder).""" | |
new_path = current_path | |
if direction == "up": | |
new_path = os.path.dirname(current_path) | |
elif direction == "enter": | |
new_path = os.path.join(current_path, path) # Path here is the selected folder | |
elif direction == "refresh": | |
new_path = current_path # Just refresh current | |
if not os.path.exists(new_path) or not os.path.isdir(new_path): | |
return [], [], current_path, "Invalid directory path." | |
return list_files_and_folders(new_path) | |
def upload_file(files, current_path): | |
"""Uploads files to the current directory.""" | |
if not files: | |
return [], [], current_path, "No files uploaded." | |
uploaded_filenames = [] | |
for file in files: | |
try: | |
filename = os.path.basename(file.name) # Get original filename | |
destination_path = os.path.join(current_path, filename) | |
if ALLOWED_EXTENSIONS_UPLOAD: # Check allowed extensions if specified | |
file_extension = os.path.splitext(filename)[1].lower() | |
if file_extension not in ALLOWED_EXTENSIONS_UPLOAD: | |
return [], [], current_path, f"File type '{file_extension}' not allowed for upload." | |
shutil.copyfile(file.name, destination_path) # Copy uploaded file | |
uploaded_filenames.append(filename) | |
except Exception as e: | |
return [], [], current_path, f"Error uploading file '{filename}': {str(e)}" | |
# Refresh file list after upload | |
return list_files_and_folders(current_path) | |
def download_file(file_path, current_path): | |
"""Returns the file path for download.""" | |
full_file_path = os.path.join(current_path, file_path) # Construct full path | |
if not os.path.isfile(full_file_path): | |
return None, "File not found for download." | |
if ALLOWED_EXTENSIONS_DOWNLOAD: # Check allowed extensions if specified | |
file_extension = os.path.splitext(full_file_path)[1].lower() | |
if file_extension not in ALLOWED_EXTENSIONS_DOWNLOAD: | |
return None, f"File type '{file_extension}' not allowed for download." | |
return full_file_path, None | |
# --- Gradio Interface --- | |
with gr.Blocks() as demo: | |
current_directory = gr.State(INITIAL_PATH) | |
with gr.Row(): | |
current_path_display = gr.Textbox(value=INITIAL_PATH, label="Current Path", interactive=False, scale=4) | |
refresh_button = gr.Button("Refresh", scale=1) | |
up_button = gr.Button("Up", scale=1) | |
with gr.Row(): | |
with gr.Column(scale=1): | |
folder_output = gr.List([], headers=["Folders"], label="Folders", elem_id="folder-list", interactive=False) # Removed type="value" | |
file_output = gr.List([], headers=["Files"], label="Files", elem_id="file-list", interactive=False) # Removed type="value" | |
with gr.Column(scale=2): | |
upload_component = gr.File(label="Upload Files", file_count="multiple") # Allows multiple file uploads | |
download_button = gr.File(label="Download Selected File") | |
error_output = gr.Markdown(label="Status") | |
# --- Functionality --- | |
def update_file_list(current_path): | |
folders, files, updated_path, error = list_files_and_folders(current_path) | |
return folders, files, updated_path, updated_path, error | |
def on_folder_select(folder_name, current_path_state): | |
return change_directory(folder_name, folder_output.value, "enter") # Corrected: use folder_output.value not folder_name directly | |
def on_up_button_click(current_path_state): | |
return change_directory("", current_path_state, "up") # Path is empty for "up" | |
def on_refresh_button_click(current_path_state): | |
return change_directory("", current_path_state, "refresh") # Path is empty for "refresh" | |
def on_file_upload(uploaded_files, current_path_state): | |
return upload_file(uploaded_files, current_path_state) | |
def on_file_select_for_download(file_name, current_path_state): | |
return download_file(file_name, current_path_state) | |
# --- Event Handlers --- | |
demo.load(update_file_list, inputs=current_directory, outputs=[folder_output, file_output, current_directory, current_path_display, error_output]) | |
folder_output.select(on_folder_select, [folder_output, current_directory], [folder_output, file_output, current_directory, current_path_display, error_output]) | |
up_button.click(on_up_button_click, inputs=current_directory, outputs=[folder_output, file_output, current_directory, current_path_display, error_output]) | |
refresh_button.click(on_refresh_button_click, inputs=current_directory, outputs=[folder_output, file_output, current_directory, current_path_display, error_output]) | |
upload_component.upload(on_file_upload, [upload_component, current_directory], [folder_output, file_output, current_directory, current_path_display, error_output] ) # clear_value=True to reset upload after submission | |
file_output.select(on_file_select_for_download, [file_output, current_directory], [download_button, error_output]) | |
if __name__ == "__main__": | |
demo.launch(share=True,server_port=1337) |