v0.0.62: лимиты 50МБ/файл, 500МБ/сессия (фронт+бэк), лимиты в UI
Deploy drhider / validate (push) Canceled after 0s
Deploy drhider / validate (push) Canceled after 0s
This commit is contained in:
+2
-2
@@ -21,7 +21,7 @@ if _sys_path_root not in sys.path:
|
||||
sys.path.insert(0, _sys_path_root)
|
||||
|
||||
# Версия приложения (меняется при изменениях)
|
||||
VERSION = "0.0.61"
|
||||
VERSION = "0.0.62"
|
||||
|
||||
|
||||
def setup_logging():
|
||||
@@ -71,7 +71,7 @@ def create_app():
|
||||
|
||||
# Конфигурация
|
||||
app.config["VERSION"] = VERSION
|
||||
app.config["MAX_CONTENT_LENGTH"] = 200 * 1024 * 1024 # 200 MB
|
||||
app.config["MAX_CONTENT_LENGTH"] = 50 * 1024 * 1024 # 50 MB (лимит на один файл)
|
||||
|
||||
# Регистрируем blueprint'ы
|
||||
from routes import register_routes
|
||||
|
||||
+23
-1
@@ -22,7 +22,8 @@ from flask import Blueprint, request, send_file, jsonify, Response, stream_with_
|
||||
|
||||
from drhider import obfuscate_files, LLMClient
|
||||
from session import (create_session, add_file, get_files, store_result,
|
||||
get_result, store_csv, get_csv, cleanup, file_count)
|
||||
get_result, store_csv, get_csv, cleanup, file_count,
|
||||
MAX_FILE_BYTES)
|
||||
|
||||
api_bp = Blueprint("api", __name__, url_prefix="/api")
|
||||
log = logging.getLogger("routes.api_bp")
|
||||
@@ -52,6 +53,10 @@ def upload():
|
||||
continue
|
||||
data = f.read()
|
||||
log.info("upload: sid=%s file=%r size=%d", sid, f.filename, len(data))
|
||||
if len(data) > MAX_FILE_BYTES:
|
||||
log.warning("upload: file exceeds %dMB, skipped sid=%s file=%r size=%d",
|
||||
MAX_FILE_BYTES // (1024 * 1024), sid, f.filename, len(data))
|
||||
continue
|
||||
if not add_file(sid, f.filename, data):
|
||||
log.warning("upload: session not found/limit, sid=%s file=%r", sid, f.filename)
|
||||
return jsonify({"ok": False, "error": "Session not found"}), 404
|
||||
@@ -89,10 +94,27 @@ def upload_refs():
|
||||
url = ref.get("url")
|
||||
if not name or not url:
|
||||
continue
|
||||
# Лимит на один файл (50 МБ): сверх лимита — пропускаем (не участвует)
|
||||
if (ref.get("size") or 0) > MAX_FILE_BYTES:
|
||||
log.warning("upload_refs: file exceeds %dMB, skip sid=%s file=%r size=%s",
|
||||
MAX_FILE_BYTES // (1024 * 1024), sid, name, ref.get("size"))
|
||||
try:
|
||||
client.delete(url)
|
||||
except Exception:
|
||||
pass
|
||||
continue
|
||||
with client.stream("GET", url) as resp:
|
||||
resp.raise_for_status()
|
||||
content = b"".join(resp.iter_bytes())
|
||||
log.info("upload_refs: pulled sid=%s file=%r size=%d", sid, name, len(content))
|
||||
if len(content) > MAX_FILE_BYTES:
|
||||
log.warning("upload_refs: pulled file exceeds %dMB, skip sid=%s file=%r size=%d",
|
||||
MAX_FILE_BYTES // (1024 * 1024), sid, name, len(content))
|
||||
try:
|
||||
client.delete(url)
|
||||
except Exception:
|
||||
pass
|
||||
continue
|
||||
if not add_file(sid, name, content):
|
||||
log.warning("upload_refs: session not found/limit, sid=%s file=%r", sid, name)
|
||||
return jsonify({"ok": False, "error": "Session not found"}), 404
|
||||
|
||||
+3
-2
@@ -21,8 +21,9 @@ from typing import Dict, List, Tuple, Optional
|
||||
|
||||
TTL_SECONDS = 30 * 60 # 30 минут
|
||||
|
||||
# Максимальный суммарный объём файлов в одной сессии (защита памяти)
|
||||
MAX_SESSION_BYTES = 500 * 1024 * 1024 # 500 MB
|
||||
# Максимальный объём одного файла и суммарный объём файлов в сессии (защита памяти)
|
||||
MAX_FILE_BYTES = 50 * 1024 * 1024 # 50 MB на один файл
|
||||
MAX_SESSION_BYTES = 500 * 1024 * 1024 # 500 MB суммарно на сессию
|
||||
|
||||
_sessions: Dict[str, dict] = {}
|
||||
_lock = threading.Lock()
|
||||
|
||||
@@ -131,7 +131,7 @@
|
||||
<p class="sub">
|
||||
Загрузите документы (.docx, .doc, .pdf, .txt, .md, .zip) — получите ZIP с обезличенными копиями.<br>
|
||||
CSV с таблицей замен скачивается отдельно.<br>
|
||||
<span style="color:#c0392b;">Ограничения: суммарно не более 1 ГБ. Файлы сверх суммарного лимита помечаются красным и не участвуют в обфускации.</span>
|
||||
<span style="color:#c0392b;">Ограничения: один файл не более 50 МБ, суммарно не более 500 МБ. Файлы сверх лимитов помечаются красным и не участвуют в обфускации.</span>
|
||||
</p>
|
||||
<div class="file-input-wrap">
|
||||
<input type="file" id="fileInput" multiple accept=".doc,.docx,.pdf,.txt,.zip">
|
||||
@@ -196,7 +196,8 @@ const db = document.getElementById('dlBtns');
|
||||
let sf = [];
|
||||
let fileMeta = new Map(); // имя -> {size, mtime} для дедупа/суффиксов
|
||||
let overNames = new Set(); // имена файлов сверх лимита (не участвуют в обфускации)
|
||||
const MAX_SESSION_BYTES = 1024 * 1024 * 1024; // 1 ГБ суммарно (лимит 100МБ/файл убран)
|
||||
const MAX_FILE_BYTES = 50 * 1024 * 1024; // 50 МБ на один файл
|
||||
const MAX_SESSION_BYTES = 500 * 1024 * 1024; // 500 МБ суммарно на сессию
|
||||
const VM_UPLOAD_URL = 'https://contracts.kube5s.ru/drhider-upload/'; // ВМ-буфер: PUT больших файлов (шлюз кластера их рвёт)
|
||||
// Тест-режим: открыть страницу с ?upload-only=1 → только загрузка, без обработки
|
||||
const TEST_UPLOAD_ONLY = new URLSearchParams(location.search).get('upload-only') === '1';
|
||||
@@ -369,11 +370,11 @@ function addFileWithDedup(file) {
|
||||
}
|
||||
fileMeta.set(name, { size, mtime });
|
||||
|
||||
// Определяем, превышает ли файл суммарный лимит (не участвует в обфускации)
|
||||
// Лимит 100МБ/файл убран — учитываются все файлы по размеру.
|
||||
// Определяем, превышает ли файл лимит (по размеру файла или суммарный) — не участвует в обфускации
|
||||
let over = false;
|
||||
if (size > MAX_FILE_BYTES) over = true; // лимит на один файл — 50 МБ
|
||||
const sum = sf.reduce((s, f) => s + (overNames.has(f.name) ? 0 : f.size), 0);
|
||||
if (sum + size > MAX_SESSION_BYTES) over = true;
|
||||
if (sum + size > MAX_SESSION_BYTES) over = true; // суммарный лимит сессии — 500 МБ
|
||||
|
||||
if (over) {
|
||||
overNames.add(name);
|
||||
|
||||
Reference in New Issue
Block a user