refactor: удалён мёртвый legacy-код загрузки напрямую (/upload, /unzip-upload, _check_ext, _unzip, ALLOWED, константы фронта); загрузка только через ВМ (/api/upload_refs)
This commit is contained in:
@@ -1,54 +1,12 @@
|
||||
"""Upload blueprint — загрузка, конвертация, распаковка."""
|
||||
import io, os, base64, hashlib, zipfile
|
||||
"""Upload-модуль: конвертация .doc→.docx + хранение/парсинг (sink для VM-буфера)."""
|
||||
import base64
|
||||
import hashlib
|
||||
|
||||
import httpx
|
||||
from flask import Blueprint, request, jsonify
|
||||
from services.parse import parse_file
|
||||
from db import documents
|
||||
import config
|
||||
|
||||
upload_bp = Blueprint("upload", __name__)
|
||||
|
||||
ALLOWED = {"pdf", "docx", "doc", "zip"}
|
||||
|
||||
|
||||
def _check_ext(filename: str) -> str | None:
|
||||
ext = filename.rsplit(".", 1)[-1].lower() if "." in filename else ""
|
||||
if ext not in ALLOWED:
|
||||
return f"unsupported format: .{ext} (allowed: {', '.join(sorted(ALLOWED))})"
|
||||
return None
|
||||
|
||||
|
||||
def _unzip(data: bytes):
|
||||
"""Распаковать ZIP → (ok, files, error)."""
|
||||
MAX_FILES = 500
|
||||
MAX_UNCOMPRESSED = 500 * 1024 * 1024 # 500 MB
|
||||
files = []
|
||||
total = 0
|
||||
try:
|
||||
with zipfile.ZipFile(io.BytesIO(data)) as zf:
|
||||
if len(zf.namelist()) > MAX_FILES:
|
||||
return False, None, f"too many files in ZIP (max {MAX_FILES})"
|
||||
for info in zf.infolist():
|
||||
if info.is_dir():
|
||||
continue
|
||||
name = os.path.basename(info.filename)
|
||||
if not name or ".." in name or "/" in name or "\\" in name:
|
||||
continue
|
||||
raw = zf.read(info)
|
||||
total += len(raw)
|
||||
if total > MAX_UNCOMPRESSED:
|
||||
return False, None, "total uncompressed size exceeds 500 MB"
|
||||
ext = name.rsplit(".", 1)[-1].lower() if "." in name else ""
|
||||
files.append({
|
||||
"filename": name,
|
||||
"ext": ext,
|
||||
"size": len(raw),
|
||||
"data_b64": base64.b64encode(raw).decode(),
|
||||
})
|
||||
except zipfile.BadZipFile:
|
||||
return False, None, "invalid ZIP archive"
|
||||
return True, files, None
|
||||
|
||||
|
||||
def _convert(filename: str, data: bytes) -> bytes:
|
||||
""".doc → .docx через внешний libreoffice-сервис. Возвращает docx-байты."""
|
||||
@@ -104,28 +62,6 @@ def _store_and_parse(filename: str, data: bytes, batch_id, contract_id, zip_sour
|
||||
return {"ok": True, "doc_id": doc["id"], "contract_id": contract_id, "parsed": parsed}
|
||||
|
||||
|
||||
@upload_bp.route("/upload", methods=["POST"])
|
||||
def upload():
|
||||
"""Загрузка одного файла + авто-парсинг → БД (прямой multipart)."""
|
||||
f = request.files.get("files")
|
||||
if not f:
|
||||
return jsonify(ok=False, error="no file"), 400
|
||||
|
||||
err = _check_ext(f.filename)
|
||||
if err:
|
||||
return jsonify(ok=False, error=err), 400
|
||||
|
||||
data = f.read()
|
||||
batch_id = request.form.get("batch_id")
|
||||
zip_source = request.form.get("zip_source")
|
||||
contract_id = request.form.get("contract_id")
|
||||
|
||||
result = _store_and_parse(f.filename, data, batch_id, contract_id, zip_source, f.content_type or "application/octet-stream")
|
||||
if not result["ok"]:
|
||||
return jsonify(ok=result["ok"], error=result.get("error"), doc_id=result.get("doc_id")), 200
|
||||
return jsonify(ok=True, doc_id=result["doc_id"], contract_id=result["contract_id"], parsed=result["parsed"])
|
||||
|
||||
|
||||
def contracts_upload_sink(name, content, batch_id=None, contract_id=None, zip_source=None):
|
||||
"""Sink для переиспользуемого модуля upload: вставить файл в documents + авто-парсинг.
|
||||
|
||||
@@ -137,15 +73,3 @@ def contracts_upload_sink(name, content, batch_id=None, contract_id=None, zip_so
|
||||
content = _convert(name, content)
|
||||
name = name[:-4] + ".docx"
|
||||
return _store_and_parse(name, content, batch_id, contract_id, zip_source)
|
||||
|
||||
|
||||
@upload_bp.route("/unzip-upload", methods=["POST"])
|
||||
def unzip_upload():
|
||||
"""Распаковать ZIP → список файлов (base64 для фронтенда, прямой multipart)."""
|
||||
f = request.files.get("files")
|
||||
if not f:
|
||||
return jsonify(ok=False, error="no file"), 400
|
||||
ok, files, err = _unzip(f.read())
|
||||
if not ok:
|
||||
return jsonify(ok=False, error=err), 400
|
||||
return jsonify(ok=True, files=files)
|
||||
|
||||
Reference in New Issue
Block a user