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) |