Spaces:
Sleeping
Sleeping
| print("=============================================") | |
| print("=== DÉMARRAGE DE MARKITDOWN WEBSERVER ===") | |
| print("=============================================") | |
| """ | |
| Serveur Flask pour MarkitDowne Local WebApp. | |
| Routes API : | |
| - GET / → Page principale | |
| - POST /upload → Upload et conversion d'un fichier | |
| - GET /history → Liste de l'historique | |
| - GET /download/<id> → Téléchargement du .md | |
| - POST /copy/<id> → Copie dans le presse-papier (retourne le texte) | |
| - POST /clear-history → Vide l'historique | |
| """ | |
| import os | |
| import uuid | |
| import socket | |
| from flask import ( | |
| Flask, | |
| render_template, | |
| request, | |
| jsonify, | |
| send_file, | |
| after_this_request, | |
| ) | |
| from converter import convert | |
| from history import add_entry, get_all, get_entry, clear | |
| app = Flask(__name__) | |
| # 1 Go max (augmenté pour supporter de gros dossiers) | |
| app.config["MAX_CONTENT_LENGTH"] = 1024 * 1024 * 1024 | |
| UPLOAD_FOLDER = os.path.join(os.path.dirname(__file__), "_uploads") | |
| os.makedirs(UPLOAD_FOLDER, exist_ok=True) | |
| # Changement du port pour 5001 afin d'éviter tout conflit avec le calculateur de piscine | |
| PORT = int(os.environ.get("PORT", 5001)) | |
| def index(): | |
| """Page principale.""" | |
| return render_template("index.html") | |
| def upload(): | |
| """ | |
| Upload et conversion d'un ou plusieurs fichiers (ou dossiers). | |
| Retourne le Markdown généré pour chaque fichier. | |
| """ | |
| print("\n--- DEBUG: Received /upload request ---") | |
| files = request.files.getlist("files") | |
| paths = request.form.getlist("paths") | |
| print(f"DEBUG: Received {len(files)} files.") | |
| print(f"DEBUG: Received {len(paths)} paths: {paths}") | |
| if not files or not paths: | |
| print("DEBUG: No files or paths received. Aborting.") | |
| return jsonify({"success": False, "error": "Aucun fichier ou chemin reçu."}), 400 | |
| if len(files) != len(paths): | |
| print("DEBUG: Mismatch between number of files and paths. Aborting.") | |
| return jsonify({"success": False, "error": "Incohérence entre les fichiers et les chemins."}), 400 | |
| results = [] | |
| errors = [] | |
| for i, file in enumerate(files): | |
| filename = paths[i] | |
| print(f"\nDEBUG: Processing file #{i+1}: {filename}") | |
| if not filename: | |
| print("DEBUG: Skipping file with empty filename.") | |
| continue | |
| base_name = os.path.basename(filename.replace("\\", "/")) | |
| temp_filename = f"{uuid.uuid4().hex}_{base_name}" | |
| temp_path = os.path.join(UPLOAD_FOLDER, temp_filename) | |
| try: | |
| file.save(temp_path) | |
| print(f"DEBUG: Saved to temporary file: {temp_path}") | |
| markdown = convert(temp_path) | |
| print("DEBUG: Conversion successful.") | |
| entry = add_entry(filename, markdown) | |
| results.append({ | |
| "id": entry["id"], | |
| "filename": filename, | |
| "markdown": markdown, | |
| "size": entry["size"], | |
| "date": entry["date"], | |
| }) | |
| except Exception as e: | |
| print(f"DEBUG: An error occurred during conversion: {e}") | |
| errors.append({"filename": filename, "error": str(e)}) | |
| finally: | |
| if os.path.exists(temp_path): | |
| try: | |
| os.remove(temp_path) | |
| print(f"DEBUG: Removed temporary file: {temp_path}") | |
| except Exception as e: | |
| print(f"DEBUG: Failed to remove temporary file: {e}") | |
| print(f"--- DEBUG: Finished processing. Results: {len(results)}, Errors: {len(errors)} ---") | |
| return jsonify({ | |
| "success": True, | |
| "results": results, | |
| "errors": errors, | |
| }) | |
| def history(): | |
| """Retourne l'historique des conversions.""" | |
| return jsonify({"success": True, "data": get_all()}) | |
| def download(entry_id): | |
| """Télécharge un fichier .md depuis l'historique.""" | |
| entry = get_entry(entry_id) | |
| if not entry: | |
| return jsonify({"success": False, "error": "Entrée introuvable."}), 404 | |
| original_filename = entry["filename"].replace("\\", "/") | |
| base = os.path.splitext(os.path.basename(original_filename))[0] | |
| md_filename = f"{base}.md" | |
| temp_md_filename = f"{uuid.uuid4().hex}_{md_filename}" | |
| md_path = os.path.join(UPLOAD_FOLDER, temp_md_filename) | |
| with open(md_path, "w", encoding="utf-8") as f: | |
| f.write(entry["markdown"]) | |
| def cleanup(response): | |
| if os.path.exists(md_path): | |
| try: | |
| os.remove(md_path) | |
| except Exception: | |
| pass | |
| return response | |
| return send_file( | |
| md_path, | |
| as_attachment=True, | |
| download_name=md_filename, | |
| mimetype="text/markdown", | |
| ) | |
| def copy(entry_id): | |
| """Retourne le contenu Markdown pour copie dans le presse-papier.""" | |
| entry = get_entry(entry_id) | |
| if not entry: | |
| return jsonify({"success": False, "error": "Entrée introuvable."}), 404 | |
| return jsonify({"success": True, "markdown": entry["markdown"]}) | |
| def clear_history(): | |
| """Vide l'historique.""" | |
| clear() | |
| return jsonify({"success": True}) | |
| # Ce bloc n'est exécuté que si on lance le script directement (ex: `python app.py`) | |
| # Il ne sera pas utilisé par Gunicorn sur Hugging Face. | |
| if __name__ == "__main__": | |
| with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: | |
| if s.connect_ex(('0.0.0.0', PORT)) == 0: | |
| print(f"ERREUR: Le port {PORT} est déjà utilisé.") | |
| print(" - Avez-vous une autre application (peut-être un autre projet) qui tourne ?") | |
| print(" - Essayez de l'arrêter et de relancer.") | |
| exit(1) | |
| print(f"\n MarkitDown WebApp lancée sur http://127.0.0.1:{PORT}\n") | |
| # On écoute sur 0.0.0.0 pour être compatible avec les conteneurs Docker | |
| app.run(host="0.0.0.0", port=PORT, debug=False) | |