fix: JSON base64 instead of multipart to avoid HTTP2 error — v0.8/v1.0.191
Deploy contracts-flask / validate (push) Successful in 0s

This commit is contained in:
2026-06-29 17:16:27 +04:00
parent 18ce26d5d3
commit 07879328ed
5 changed files with 34 additions and 34 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ DrHider — обфускация документов (двухпроходна
Согласованность: одна и та же сущность во всех файлах → одно и то же фиктивное значение.
"""
DRHIDER_VERSION = "0.7"
DRHIDER_VERSION = "0.8"
import io
import csv
import re
+11 -5
View File
@@ -110,17 +110,23 @@ def drhider():
@app.route("/api/drhider", methods=["POST"])
def api_drhider():
"""Обфускация: файлы → ZIP."""
import io
"""Обфускация: JSON {files: [{name, data: base64}]} → ZIP."""
import io, base64
from flask import send_file
from services.drhider import obfuscate_files
from services.llm_client import HttpxLLMClient
uploaded = request.files.getlist("files")
if not uploaded:
body = request.get_json(silent=True) or {}
raw_files = body.get("files", [])
if not raw_files:
return jsonify({"ok": False, "error": "Нет файлов"}), 400
files = [(f.filename, f.read(), f.content_type or "") for f in uploaded if f.filename]
files = []
for f in raw_files:
name = f.get("name", "unnamed")
data = base64.b64decode(f.get("data", ""))
files.append((name, data, f.get("type", "")))
if not files:
return jsonify({"ok": False, "error": "Нет файлов"}), 400
+1 -1
View File
@@ -6,7 +6,7 @@ DrHider — обфускация документов (двухпроходна
Согласованность: одна и та же сущность во всех файлах → одно и то же фиктивное значение.
"""
DRHIDER_VERSION = "0.7"
DRHIDER_VERSION = "0.8"
import io
import csv
import re
+20 -26
View File
@@ -64,7 +64,7 @@
<a href="/">Сверка договоров</a>
<span class="sep">|</span>
<strong>DrHider</strong>
<span style="font-size:11px;color:var(--muted);">v0.7</span>
<span style="font-size:11px;color:var(--muted);">v0.8</span>
</header>
<main>
@@ -121,33 +121,27 @@ function render() {
BTN.onclick = async () => {
if (!files.length) return;
BTN.disabled = true;
setStatus('progress', '⏳ Отправка...');
const fd = new FormData(); files.forEach(f => fd.append('files', f));
setStatus('progress', '⏳ Чтение файлов...');
try {
// Шаг 1: старт задачи
const r1 = await fetch('/api/drhider', { method:'POST', body:fd });
if (!r1.ok) throw new Error(await r1.text());
const j = await r1.json();
if (!j.ok) throw new Error(j.error);
const jobId = j.job_id;
// Шаг 2: опрос
for (let i = 0; i < 120; i++) {
await new Promise(r => setTimeout(r, 2000));
const r2 = await fetch('/api/drhider/' + jobId + '/status');
const s = await r2.json();
if (s.error) throw new Error(s.error);
if (s.done) {
setStatus('progress', '⏳ Скачивание...');
const r3 = await fetch('/api/drhider/' + jobId + '/download');
if (!r3.ok) throw new Error(await r3.text());
const blob = await r3.blob();
const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = 'drhider_output.zip'; a.click();
const payload = [];
for (const f of files) {
const buf = await f.arrayBuffer();
const b64 = btoa(String.fromCharCode(...new Uint8Array(buf)));
payload.push({name: f.name, data: b64, type: f.type || ''});
}
setStatus('progress', '⏳ Обработка...');
const r = await fetch('/api/drhider', {
method:'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({files: payload})
});
if (!r.ok) throw new Error(await r.text());
const blob = await r.blob();
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = 'drhider_output.zip';
a.click();
setStatus('done', '✅ Готово!');
break;
}
setStatus('progress', '⏳ Обработка... (' + ((i+1)*2) + 'с)');
}
} catch(e) {
setStatus('error', '❌ ' + (e.message || 'Ошибка'));
}
+1 -1
View File
@@ -73,7 +73,7 @@
<body>
<div class="topbar">
<img src="/static/logo.svg" alt="Nubes">
<span class="title">Сверка договоров — LLM AI-driven Event Sourcing <span style="font-weight:400;color:var(--muted);font-size:12px;">v1.0.190-flask</span></span>
<span class="title">Сверка договоров — LLM AI-driven Event Sourcing <span style="font-weight:400;color:var(--muted);font-size:12px;">v1.0.191-flask</span></span>
<div id="pipelineStepper" style="display:flex;gap:8px;font-size:11px;align-items:center;color:var(--muted);">
<span id="stepUpload">○ Загрузка</span><span></span>
<span id="stepClassify">○ Классификация</span><span></span>