Spaces:
Sleeping
Sleeping
File size: 6,124 Bytes
898ed62 0090d2e 898ed62 7ece4a1 898ed62 | 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 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | 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))
@app.route("/")
def index():
"""Page principale."""
return render_template("index.html")
@app.route("/upload", methods=["POST"])
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,
})
@app.route("/history")
def history():
"""Retourne l'historique des conversions."""
return jsonify({"success": True, "data": get_all()})
@app.route("/download/<entry_id>")
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"])
@after_this_request
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",
)
@app.route("/copy/<entry_id>")
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"]})
@app.route("/clear-history", methods=["POST"])
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)
|