From e4975fb37ee464877a09d23b9dd3d49b9332dd60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Mon, 13 Jul 2026 10:40:00 +0400 Subject: [PATCH] =?UTF-8?q?v0.0.5:=20CSV=20=D0=BE=D1=82=D0=B4=D0=B5=D0=BB?= =?UTF-8?q?=D1=8C=D0=BD=D0=BE,=20timestamp=20=D0=B8=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D0=B0,=20=D0=BF=D1=80=D0=BE=D0=B3=D1=80=D0=B5=D1=81=D1=81=20?= =?UTF-8?q?=D0=B2=20=D1=82=D0=B0=D0=B1=D0=BB=D0=B8=D1=86=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- site/app.py | 2 +- site/routes/api_bp.py | 32 +++++++-- site/session.py | 32 +++++++++ site/templates/index.html | 141 +++++++++++++++++++++++++++++++++++++- 4 files changed, 197 insertions(+), 10 deletions(-) diff --git a/site/app.py b/site/app.py index 6d2cf36..8ed38c9 100644 --- a/site/app.py +++ b/site/app.py @@ -20,7 +20,7 @@ if _sys_path_root not in sys.path: sys.path.insert(0, _sys_path_root) # Версия приложения (меняется при изменениях) -VERSION = "0.0.4" +VERSION = "0.0.5" def create_app(): diff --git a/site/routes/api_bp.py b/site/routes/api_bp.py index a32b301..a00f648 100644 --- a/site/routes/api_bp.py +++ b/site/routes/api_bp.py @@ -1,20 +1,23 @@ """ Blueprint: API DrHider. -Three endpoints: +Four endpoints: - POST /api/upload — upload one file -> {session_id} - POST /api/process/{sid} — process all session files -> {status:"done"} -- GET /api/download/{sid} — download ZIP +- GET /api/download/{sid} — download ZIP (with timestamp name) +- GET /api/csv/{sid} — download CSV separately """ import io import zipfile import traceback +from datetime import datetime from flask import Blueprint, request, send_file, jsonify from drhider import obfuscate_files, LLMClient from drhider.builder import build_zip, build_mapping_csv -from session import create_session, add_file, get_files, store_result, get_result, cleanup, file_count +from session import (create_session, add_file, get_files, store_result, + get_result, store_csv, get_csv, cleanup, file_count) api_bp = Blueprint("api", __name__, url_prefix="/api") @@ -64,8 +67,10 @@ def process(sid): elif not name.endswith("/"): all_results.append((name, zf.read(name))) csv_str = build_mapping_csv(all_mapping) if all_mapping else "" - final_zip = build_zip(all_results, mapping_csv=csv_str) + final_zip = build_zip(all_results) # CSV — отдельно, не в ZIP store_result(sid, final_zip) + if csv_str: + store_csv(sid, csv_str) return jsonify({"ok": True, "status": "done", "files": len(all_results)}) except Exception as e: traceback.print_exc() @@ -78,6 +83,21 @@ def download(sid): zip_data = get_result(sid) if zip_data is None: return jsonify({"ok": False, "error": "Not found"}), 404 - cleanup(sid) + ts = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") return send_file(io.BytesIO(zip_data), mimetype="application/zip", - as_attachment=True, download_name="drhider_output.zip") + as_attachment=True, download_name=f"drhider_{ts}.zip") + + +@api_bp.route("/csv/", methods=["GET"]) +def csv_download(sid): + """Download CSV separately.""" + csv_str = get_csv(sid) + if csv_str is None: + return jsonify({"ok": False, "error": "Not found"}), 404 + cleanup(sid) + ts = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + buf = io.BytesIO() + buf.write('\ufeff'.encode('utf-8') + csv_str.encode('utf-8')) + buf.seek(0) + return send_file(buf, mimetype="text/csv", + as_attachment=True, download_name=f"mapping_{ts}.csv") diff --git a/site/session.py b/site/session.py index 4b0b7e5..66e1822 100644 --- a/site/session.py +++ b/site/session.py @@ -136,3 +136,35 @@ def cleanup(sid: str): s = _sessions.pop(sid, None) if s and s.get("timer"): s["timer"].cancel() + + +def store_csv(sid: str, csv_str: str) -> bool: + """Сохранить CSV с таблицей замен. + + Args: + sid: Идентификатор сессии + csv_str: Строка CSV + + Returns: + True если сессия существует, False если нет. + """ + with _lock: + s = _sessions.get(sid) + if not s: + return False + s["csv"] = csv_str + return True + + +def get_csv(sid: str) -> Optional[str]: + """Получить CSV с таблицей замен. + + Args: + sid: Идентификатор сессии + + Returns: + Строка CSV или None если нет. + """ + with _lock: + s = _sessions.get(sid) + return s.get("csv") if s else None diff --git a/site/templates/index.html b/site/templates/index.html index 2846504..929c465 100644 --- a/site/templates/index.html +++ b/site/templates/index.html @@ -3,6 +3,9 @@ + + + DrHider — обфускация документов @@ -66,6 +90,13 @@
Обфускация документов
+

+ Загрузите документы (.docx, .pdf, .txt, .zip) — получите ZIP с обезличенными копиями.
+ CSV с таблицей замен скачивается отдельно. +

+
+ +
@@ -76,17 +107,121 @@ - +
Нет выбранных файлов
+
+
+ +
+