fix: Support multiple file types (PNG, PDF, JPEG) for DokuWiki media uploads
- Make upload_media accept ir.attachment records, IDs, or raw bytes - Detect file extension from binary content using imghdr - Build media_id with correct extension (.png, .jpg, .pdf) - Prevent DokuWiki 'file extension mismatch' error - Improve temp file cleanup with proper error handling
This commit is contained in:
parent
38d0becfad
commit
b26e70dbe9
|
|
@ -278,27 +278,93 @@ class DokuWikiClient(models.AbstractModel):
|
|||
UserError: Bei Fehler beim Upload
|
||||
"""
|
||||
wiki = self._get_wiki_connection()
|
||||
|
||||
|
||||
import tempfile
|
||||
import os
|
||||
|
||||
# Temporäre Datei erstellen (dokuwiki.py erwartet Datei-Pfad)
|
||||
with tempfile.NamedTemporaryFile(delete=False, suffix='.jpg') as tmp_file:
|
||||
tmp_file.write(file_content)
|
||||
tmp_path = tmp_file.name
|
||||
|
||||
import base64
|
||||
import imghdr
|
||||
|
||||
tmp_path = None
|
||||
|
||||
# Unterstütze mehrere Eingabetypen:
|
||||
# - ir.attachment record (Recordset)
|
||||
# - attachment id (int)
|
||||
# - rohe Bytes
|
||||
# - base64-codierter String
|
||||
try:
|
||||
wiki.medias.add(media_id, tmp_path, overwrite=overwrite)
|
||||
_logger.info(f"Mediendatei hochgeladen: {media_id}")
|
||||
return True
|
||||
except DokuWikiError as e:
|
||||
error_msg = f"Fehler beim Hochladen der Mediendatei {media_id}: {e}"
|
||||
_logger.error(error_msg)
|
||||
raise UserError(error_msg)
|
||||
content_bytes = None
|
||||
ext = ''
|
||||
|
||||
# ir.attachment Record
|
||||
if hasattr(file_content, '_name') and getattr(file_content, '_name') == 'ir.attachment':
|
||||
att = file_content.sudo()
|
||||
if not att.datas:
|
||||
raise UserError(f"Attachment {att.id} enthält keine Daten")
|
||||
content_bytes = base64.b64decode(att.datas)
|
||||
fname = att.datas_fname or ''
|
||||
ext = os.path.splitext(fname)[1]
|
||||
|
||||
# attachment id
|
||||
elif isinstance(file_content, int):
|
||||
att = self.env['ir.attachment'].sudo().browse(file_content)
|
||||
if not att.exists() or not att.datas:
|
||||
raise UserError(f"Attachment {file_content} nicht gefunden oder leer")
|
||||
content_bytes = base64.b64decode(att.datas)
|
||||
fname = att.datas_fname or ''
|
||||
ext = os.path.splitext(fname)[1]
|
||||
|
||||
# base64 string
|
||||
elif isinstance(file_content, str):
|
||||
try:
|
||||
content_bytes = base64.b64decode(file_content)
|
||||
except Exception:
|
||||
# Fallback: treat as empty
|
||||
raise UserError("Übergebener String konnte nicht als base64 decodiert werden")
|
||||
ext = os.path.splitext(media_id)[1]
|
||||
|
||||
# rohe bytes
|
||||
else:
|
||||
# assume bytes-like
|
||||
content_bytes = file_content
|
||||
# try extension from media_id
|
||||
ext = os.path.splitext(media_id)[1]
|
||||
|
||||
# Wenn noch keine Extension, versuche Bildtyp zu erkennen
|
||||
if not ext:
|
||||
try:
|
||||
img_type = imghdr.what(None, content_bytes)
|
||||
if img_type:
|
||||
ext = f'.{img_type}'
|
||||
except Exception:
|
||||
ext = ''
|
||||
|
||||
if not ext:
|
||||
ext = '.bin'
|
||||
|
||||
# Sicherstellen, dass ext mit Punkt beginnt
|
||||
if not ext.startswith('.'):
|
||||
ext = f'.{ext}'
|
||||
|
||||
# Temporäre Datei erstellen (dokuwiki.py erwartet Datei-Pfad)
|
||||
with tempfile.NamedTemporaryFile(delete=False, suffix=ext) as tmp_file:
|
||||
tmp_file.write(content_bytes)
|
||||
tmp_path = tmp_file.name
|
||||
|
||||
try:
|
||||
wiki.medias.add(media_id, tmp_path, overwrite=overwrite)
|
||||
_logger.info(f"Mediendatei hochgeladen: {media_id} (tmp={tmp_path})")
|
||||
return True
|
||||
except DokuWikiError as e:
|
||||
error_msg = f"Fehler beim Hochladen der Mediendatei {media_id}: {e}"
|
||||
_logger.error(error_msg)
|
||||
raise UserError(error_msg)
|
||||
finally:
|
||||
# Temporäre Datei löschen
|
||||
if os.path.exists(tmp_path):
|
||||
os.unlink(tmp_path)
|
||||
if tmp_path and os.path.exists(tmp_path):
|
||||
try:
|
||||
os.unlink(tmp_path)
|
||||
except Exception:
|
||||
_logger.warning(f"Konnte temporäre Datei nicht löschen: {tmp_path}")
|
||||
|
||||
@api.model
|
||||
def get_media_url(self, media_id):
|
||||
|
|
|
|||
|
|
@ -399,17 +399,35 @@ class MaintenanceEquipment(models.Model):
|
|||
)
|
||||
# Area-Name normalisieren (wie bei Pages)
|
||||
area_name = self._normalize_wiki_name(self.ows_area_id.name) if self.ows_area_id else 'unbekannt'
|
||||
media_id = f"{equipment_namespace}:{area_name}:{wiki_doku_id}.jpg"
|
||||
|
||||
# Bild ins Wiki hochladen
|
||||
# Bild ins Wiki hochladen (erkenne Extension aus Bytes)
|
||||
try:
|
||||
import base64
|
||||
import imghdr
|
||||
|
||||
# image_1920 ist base64-kodiert, in bytes umwandeln für XML-RPC
|
||||
image_bytes = base64.b64decode(self.image_1920)
|
||||
|
||||
|
||||
# Typ/Extension erkennen (jpeg -> .jpg)
|
||||
img_type = None
|
||||
try:
|
||||
img_type = imghdr.what(None, image_bytes)
|
||||
except Exception:
|
||||
img_type = None
|
||||
|
||||
if img_type == 'jpeg':
|
||||
ext = '.jpg'
|
||||
elif img_type:
|
||||
ext = f'.{img_type}'
|
||||
elif image_bytes.startswith(b'%PDF'):
|
||||
ext = '.pdf'
|
||||
else:
|
||||
ext = '.bin'
|
||||
|
||||
media_id = f"{equipment_namespace}:{area_name}:{wiki_doku_id}{ext}"
|
||||
|
||||
dokuwiki_client = self.env['dokuwiki.client']
|
||||
dokuwiki_client.upload_media(media_id, image_bytes, overwrite=True)
|
||||
|
||||
|
||||
# DokuWiki Image-Syntax: {{namespace:file.jpg?300}}
|
||||
values['image'] = f"{{{{:{media_id}?100}}}}"
|
||||
values['image_large'] = f"{{{{:{media_id}}}}}"
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user