v0.0.30: .doc поддержка — accept + liberta API вместо LibreOffice
Deploy drhider / validate (push) Waiting to run

This commit is contained in:
2026-07-16 11:28:16 +04:00
parent c102d54887
commit 87a6df45c5
3 changed files with 26 additions and 32 deletions
+24 -30
View File
@@ -149,14 +149,14 @@ def pdf_to_markdown(content: bytes) -> str:
# ═══════════════════════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════════════════════
# DOC → Markdown (через LibreOffice) # DOC → Markdown (через сервис liberta)
# ═══════════════════════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════════════════════
def doc_to_markdown(content: bytes) -> str: def doc_to_markdown(content: bytes) -> str:
"""Конвертировать бинарный .doc → .docx (LibreOffice) → Markdown. """Конвертировать бинарный .doc → .docx (сервис liberta) → Markdown.
Использует soffice --headless --convert-to docx, затем прогоняет Отправляет .doc на HTTP-сервис конвертации, получает .docx,
через штатный docx_to_markdown() с полным форматированием и таблицами. затем прогоняет через штатный docx_to_markdown().
Args: Args:
content: Бинарное содержимое .doc файла content: Бинарное содержимое .doc файла
@@ -164,33 +164,27 @@ def doc_to_markdown(content: bytes) -> str:
Returns: Returns:
Строка в формате Markdown (или сообщение об ошибке) Строка в формате Markdown (или сообщение об ошибке)
""" """
tmpdir = tempfile.mkdtemp() import httpx
doc_path = os.path.join(tmpdir, "input.doc") url = os.environ.get(
"CONVERT_SERVICE_URL",
"https://liberta.containerk8s.dev.nubes.ru/convert"
)
try: try:
with open(doc_path, 'wb') as f: with httpx.Client(timeout=120) as client:
f.write(content) resp = client.post(
url,
result = subprocess.run( files={"file": ("input.doc", content, "application/msword")}
["soffice", "--headless", "--convert-to", "docx", )
"--outdir", tmpdir, doc_path], if resp.status_code == 200:
timeout=60, capture_output=True return docx_to_markdown(resp.content)
) err = resp.json().get("error", f"HTTP {resp.status_code}")
log.warning("liberta conversion failed: %s", err)
docx_path = os.path.join(tmpdir, "input.docx") return f"[DOC — conversion failed: {err}]"
if os.path.exists(docx_path): except httpx.TimeoutException:
with open(docx_path, 'rb') as f: return "[DOC — conversion timed out (>120s)]"
return docx_to_markdown(f.read()) except Exception as e:
log.warning("liberta error: %s", e)
stderr = result.stderr.decode('utf-8', errors='replace').strip() return f"[DOC — conversion error: {e}]"
log.warning("LibreOffice conversion failed: %s", stderr)
return f"[DOC — LibreOffice conversion failed: {stderr}]"
except FileNotFoundError:
return "[DOC — LibreOffice not installed. Install: apt install libreoffice-writer]"
except subprocess.TimeoutExpired:
return "[DOC — conversion timed out (>60s)]"
finally:
shutil.rmtree(tmpdir, ignore_errors=True)
# ═══════════════════════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════════════════════
+1 -1
View File
@@ -20,7 +20,7 @@ if _sys_path_root not in sys.path:
sys.path.insert(0, _sys_path_root) sys.path.insert(0, _sys_path_root)
# Версия приложения (меняется при изменениях) # Версия приложения (меняется при изменениях)
VERSION = "0.0.29" VERSION = "0.0.30"
def create_app(): def create_app():
+1 -1
View File
@@ -101,7 +101,7 @@
CSV с таблицей замен скачивается отдельно. CSV с таблицей замен скачивается отдельно.
</p> </p>
<div class="file-input-wrap"> <div class="file-input-wrap">
<input type="file" id="fileInput" multiple accept=".docx,.pdf,.txt,.zip"> <input type="file" id="fileInput" multiple accept=".doc,.docx,.pdf,.txt,.zip">
</div> </div>
<div class="table-wrap"> <div class="table-wrap">
<table> <table>