1 Commits

Author SHA1 Message Date
Stéphan Sainléger
fb7ff241f5 [FIX] hr_expense_report_merge_attachment: handle HEIC images uploaded as JPEG
Some iPhone users upload HEIC files with a ``.jpg`` extension. Odoo stores
the file as-is, but the mimetype is detected as ``image/...``, so the code
enters the image processing branch. ``reportlab``'s ``ImageReader`` relies
on ``PIL.Image.open()`` which cannot identify HEIC files without an explicit
plugin, causing a ``PIL.UnidentifiedImageError`` and a 500 error on report
download.

Fix by:
- Registering the ``pillow-heif`` opener at module load time (optional
  dependency, silently ignored if not installed) so that Pillow can decode
  HEIC/HEIF images.
- Converting any image to JPEG in memory via Pillow before passing it to
  ``ImageReader``, bypassing ``reportlab``'s own format detection entirely.
- Wrapping the image block in a ``try/except`` to gracefully skip
  attachments that cannot be decoded, consistent with the existing PDF
  error handling.
2026-05-15 13:36:43 +02:00

View File

@@ -9,6 +9,11 @@ from odoo import http
from reportlab.pdfgen import canvas
from reportlab.lib.utils import ImageReader
from reportlab.lib.pagesizes import letter, A4
try:
from pillow_heif import register_heif_opener
register_heif_opener()
except ImportError:
pass
logger = logging.getLogger(__name__)
@@ -50,14 +55,25 @@ class Extension(main.ReportController):
except PyPDF2.utils.PdfReadError: # Case of non-pdf attachments
logger.info('Attachment %s cannot be merged in expense report'%(att.name,))
elif 'image/' in att.mimetype:
packet = io.BytesIO()
can = canvas.Canvas(packet)
img = ImageReader(io.BytesIO(base64.b64decode(att.datas)))
can.drawImage(img, 0, 0, A4[0]*0.9, A4[1]*0.9, preserveAspectRatio=True)
can.save()
packet.seek(0)
attachment_reader = OdooPdfFileReader(packet)
writer.addPage(attachment_reader.getPage(0))
try:
from PIL import Image as PilImage
raw = base64.b64decode(att.datas)
pil_img = PilImage.open(io.BytesIO(raw))
if pil_img.mode not in ('RGB', 'RGBA'):
pil_img = pil_img.convert('RGB')
jpeg_buffer = io.BytesIO()
pil_img.save(jpeg_buffer, format='JPEG')
jpeg_buffer.seek(0)
packet = io.BytesIO()
can = canvas.Canvas(packet)
img = ImageReader(jpeg_buffer)
can.drawImage(img, 0, 0, A4[0]*0.9, A4[1]*0.9, preserveAspectRatio=True)
can.save()
packet.seek(0)
attachment_reader = OdooPdfFileReader(packet)
writer.addPage(attachment_reader.getPage(0))
except Exception:
logger.info('Attachment %s cannot be merged in expense report', att.name)
# Write new pdf to res.data
buffer = io.BytesIO()
@@ -66,4 +82,4 @@ class Extension(main.ReportController):
res.data = pdf_content
return res
return res