107 lines
3.6 KiB
Python
107 lines
3.6 KiB
Python
"""export_prilohy.py – export příloh z Medicus FILES tabulky do souborů
|
||
|
||
Extrahuje všechny záznamy z FILES, uloží BODY blob jako soubor.
|
||
Detekuje dva formáty BODY:
|
||
- inline PDF (začíná %PDF)
|
||
- reference (začíná magic \xee\xbb\xaa\x0b) → čte z externí MEDICUS_FILES_YYYYMM.fdb
|
||
"""
|
||
|
||
import os
|
||
import struct
|
||
import sys
|
||
|
||
sys.path.insert(0, r'U:\OrdinaceProjekt')
|
||
from Knihovny.najdi_dropbox import get_dropbox_root
|
||
from Knihovny.medicus_db import get_medicus_connection
|
||
|
||
# ─── Konfigurace ─────────────────────────────────────────────────────────────
|
||
|
||
OUTPUT_DIR = os.path.join(get_dropbox_root(), r'!!!Days\Downloads Z230\Files')
|
||
RECORDS_COUNT = 0 # 0 = všechny záznamy
|
||
|
||
# Magic bytes identifikující referenci na externí FDB (na reporterovi nenastane)
|
||
MAGIC = b'\xee\xbb\xaa\x0b'
|
||
|
||
# ─── Pomocné funkce ───────────────────────────────────────────────────────────
|
||
|
||
def parse_body_ref(body_bytes):
|
||
"""Vrátí (uid, dbname) pokud BODY je reference na ext FDB, jinak None."""
|
||
if not body_bytes or len(body_bytes) < 8:
|
||
return None
|
||
if body_bytes[:4] != MAGIC:
|
||
return None
|
||
uid = body_bytes[4:36].decode('ascii')
|
||
dblen = struct.unpack_from('<I', body_bytes, 36)[0]
|
||
dbname = body_bytes[40:40 + dblen].decode('ascii')
|
||
return uid, dbname
|
||
|
||
|
||
def safe_filename(name):
|
||
"""Odstraní znaky nevhodné pro název souboru."""
|
||
for ch in r'\/:*?"<>|':
|
||
name = name.replace(ch, '_')
|
||
return name.strip()
|
||
|
||
|
||
# ─── Hlavní logika ────────────────────────────────────────────────────────────
|
||
|
||
def main():
|
||
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
||
|
||
conn = get_medicus_connection()
|
||
cur = conn.cursor()
|
||
limit = f"FIRST {RECORDS_COUNT} " if RECORDS_COUNT > 0 else ""
|
||
cur.execute(f"""
|
||
SELECT {limit}f.ID, f.IDPAC, f.DATUM, f.FILENAME, f.BODY, f.POZNAMKA
|
||
FROM FILES f
|
||
ORDER BY f.ID
|
||
""")
|
||
|
||
ok = 0
|
||
chyb = 0
|
||
|
||
for row in cur:
|
||
file_id, idpac, datum, filename, body_blob, poznamka = row
|
||
|
||
# Přečti blob
|
||
try:
|
||
if hasattr(body_blob, 'read'):
|
||
body_bytes = body_blob.read()
|
||
body_blob.close()
|
||
else:
|
||
body_bytes = body_blob or b''
|
||
except Exception as e:
|
||
print(f" [CHYBA] ID={file_id}: čtení BODY selhalo: {e}")
|
||
chyb += 1
|
||
continue
|
||
|
||
# Zjisti formát
|
||
ref = parse_body_ref(body_bytes)
|
||
if ref:
|
||
_, dbname = ref
|
||
print(f" [SKIP] ID={file_id}: reference na ext DB {dbname} — nepodporováno")
|
||
chyb += 1
|
||
continue
|
||
pdf_data = body_bytes
|
||
|
||
# Sestavení cílového názvu: ID_IDPAC_DATUM_filename
|
||
datum_str = datum.strftime('%Y-%m-%d') if datum else 'bez-data'
|
||
raw_fn = filename or f'soubor_{file_id}.bin'
|
||
out_name = f"{file_id:06d}_{idpac:06d}_{datum_str}_{safe_filename(raw_fn)}"
|
||
out_path = os.path.join(OUTPUT_DIR, out_name)
|
||
|
||
# Ulož
|
||
with open(out_path, 'wb') as f:
|
||
f.write(pdf_data)
|
||
|
||
print(f" ID={file_id} idpac={idpac} {datum_str} {raw_fn} → {len(pdf_data):,} B")
|
||
ok += 1
|
||
|
||
conn.close()
|
||
print(f"\nHotovo: {ok} uloženo, {chyb} chyb")
|
||
print(f"Výstup: {OUTPUT_DIR}")
|
||
|
||
|
||
if __name__ == '__main__':
|
||
main()
|