From 42d6dc095928ca712099423c21de52e3a2de2389 Mon Sep 17 00:00:00 2001 From: Sanchit Minda Date: Fri, 6 Feb 2026 08:39:05 +0000 Subject: [PATCH] adding --- app.py | 119 ++++++++++++++++++++++++ templates/index.html | 216 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 335 insertions(+) create mode 100644 app.py create mode 100644 templates/index.html diff --git a/app.py b/app.py new file mode 100644 index 0000000..6b2e0c4 --- /dev/null +++ b/app.py @@ -0,0 +1,119 @@ +import os +import mimetypes +from flask import Flask, render_template, request, jsonify, send_file, abort + +app = Flask(__name__) + +# Configuration +IGNORE_FOLDERS = {'.git', '__pycache__', 'node_modules', '$RECYCLE.BIN', 'System Volume Information'} + +def get_file_info(filepath): + """Helper to extract file details.""" + try: + stats = os.stat(filepath) + mime_type, _ = mimetypes.guess_type(filepath) + return { + "name": os.path.basename(filepath), + "path": filepath, + "size": stats.st_size, + "is_dir": os.path.isdir(filepath), + "mime": mime_type or "application/octet-stream" + } + except PermissionError: + return None + +@app.route('/') +def index(): + """Serves the main UI.""" + # Default to current working directory + start_path = os.getcwd() + return render_template('index.html', start_path='/toor') + +@app.route('/api/scan') +def scan_files(): + """ + Scans a directory. + Query Params: + - path: The root path to scan. + - recursive: 'true' to scan subfolders, 'false' for just top level. + """ + root_path = request.args.get('path', '.') + recursive = request.args.get('recursive', 'false') == 'true' + + if not os.path.exists(root_path): + return jsonify({"error": "Path does not exist"}), 404 + + file_list = [] + + try: + if recursive: + # Recursive walk (Limit to avoid freezing on massive drives) + file_count = 0 + MAX_FILES = 2000 + + for root, dirs, files in os.walk(root_path): + # Filter out ignored folders + dirs[:] = [d for d in dirs if d not in IGNORE_FOLDERS] + + for name in files: + if file_count >= MAX_FILES: + break + full_path = os.path.join(root, name) + info = get_file_info(full_path) + if info: + file_list.append(info) + file_count += 1 + if file_count >= MAX_FILES: + break + else: + # Standard directory listing (Non-recursive) + print(f"Scanning {root_path}") + with os.scandir(root_path) as entries: + for entry in entries: + info = get_file_info(entry.path) + if info: + file_list.append(info) + except Exception as e: + return jsonify({"error": str(e)}), 500 + + # Sort: Directories first, then files + file_list.sort(key=lambda x: (not x['is_dir'], x['name'].lower())) + + return jsonify({"files": file_list, "current_path": root_path}) + +@app.route('/api/download') +def download_file(): + """Downloads a specific file.""" + filepath = request.args.get('path') + if not filepath or not os.path.exists(filepath): + return abort(404) + return send_file(filepath, as_attachment=True) + +@app.route('/api/preview') +def preview_file(): + """Serves file content for preview (images/audio).""" + filepath = request.args.get('path') + if not filepath or not os.path.exists(filepath): + return abort(404) + return send_file(filepath, as_attachment=False) + +@app.route('/api/delete', methods=['DELETE']) +def delete_file(): + """Deletes a file.""" + filepath = request.args.get('path') + if not filepath or not os.path.exists(filepath): + return jsonify({"error": "File not found"}), 404 + + try: + if os.path.isdir(filepath): + os.rmdir(filepath) # Only removes empty dirs for safety + else: + os.remove(filepath) + return jsonify({"success": True}) + except Exception as e: + return jsonify({"error": str(e)}), 500 + +if __name__ == '__main__': + # Run on localhost + print("Starting File Explorer on http://127.0.0.1:80") + app.run(debug=True, port=5005, host='0.0.0.0') diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..56c1e89 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,216 @@ + + + + + + Sam File Explorer + + + + + + +
+
+

File Explorer

+
+ + +
+
+
+
+ Path + + +
+
+
+
+ + +
+
+
+
+ + +
+ + + + + + + + + + + + +
NameSizeActions
+
+
+

Scanning files...

+
+
+
+ + + + + + + + +