feat: convert DOCX to PDF on-the-fly for inline viewing
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions

DOCX/DOC documents are now converted to PDF using LibreOffice headless
when the user clicks "Otwórz". The converted PDF is cached next to the
original file so subsequent views are instant.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Maciej Pienczyn 2026-02-20 12:46:41 +01:00
parent 8893e01d1c
commit 52eb79f87d

View File

@ -22,6 +22,8 @@ Endpoints - Documents:
"""
import os
import subprocess
import tempfile
from datetime import datetime
from flask import (
render_template, request, redirect, url_for, flash,
@ -537,7 +539,7 @@ def document_download(doc_id):
@login_required
@rada_member_required
def document_view(doc_id):
"""Open a PDF document inline in the browser"""
"""Open a document inline in the browser (converts DOCX to PDF on the fly)"""
db = SessionLocal()
try:
doc = db.query(BoardDocument).filter(
@ -558,6 +560,34 @@ def document_view(doc_id):
flash('Plik dokumentu nie został znaleziony na serwerze.', 'error')
return redirect(url_for('board.meeting_view', meeting_id=doc.meeting_id))
# DOCX/DOC: convert to PDF for inline viewing
if doc.file_extension in ('docx', 'doc'):
pdf_path = file_path.rsplit('.', 1)[0] + '.pdf'
# Convert only if cached PDF doesn't exist
if not os.path.exists(pdf_path):
try:
result = subprocess.run(
['libreoffice', '--headless', '--convert-to', 'pdf',
'--outdir', os.path.dirname(file_path), file_path],
capture_output=True, timeout=30
)
if result.returncode != 0:
current_app.logger.error(f"DOCX to PDF conversion failed: {result.stderr.decode()}")
flash('Nie udało się przekonwertować dokumentu do PDF.', 'error')
return redirect(url_for('board.meeting_view', meeting_id=doc.meeting_id))
except subprocess.TimeoutExpired:
flash('Konwersja dokumentu trwała za długo.', 'error')
return redirect(url_for('board.meeting_view', meeting_id=doc.meeting_id))
pdf_name = doc.original_filename.rsplit('.', 1)[0] + '.pdf'
return send_file(
pdf_path,
mimetype='application/pdf',
as_attachment=False,
download_name=pdf_name
)
return send_file(
file_path,
mimetype=doc.mime_type,