fix: properly decode base64 image data and detect MIME type

Image endpoint was returning base64 text instead of decoded binary.
Now properly decodes base64 from Odoo Binary field and detects actual
content type from magic bytes (JPEG, PNG, GIF, WebP).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-04-01 21:57:14 -04:00
parent 1a679a45c3
commit 8c01deb2e3

View File

@@ -23,16 +23,45 @@ class WooApiController(http.Controller):
try:
line = request.env['woo.variant.push.line'].sudo().browse(line_id)
if not line.exists() or not line.image:
_logger.warning("Image endpoint: line %d not found or no image", line_id)
return request.not_found()
img_data = line.image
if isinstance(img_data, str):
# Odoo Binary fields always return base64 string
if isinstance(img_data, (str, bytes)):
if isinstance(img_data, bytes):
img_data = img_data.decode('utf-8')
img_data = base64.b64decode(img_data)
elif isinstance(img_data, memoryview):
img_data = bytes(img_data)
# Raw bytea from DB — still base64 encoded by ORM
raw = bytes(img_data)
try:
img_data = base64.b64decode(raw)
except Exception:
img_data = raw
# Detect content type from magic bytes
content_type = 'image/png'
if filename.lower().endswith('.jpg') or filename.lower().endswith('.jpeg'):
if img_data[:2] == b'\xff\xd8':
content_type = 'image/jpeg'
return Response(img_data, content_type=content_type, status=200)
elif img_data[:4] == b'\x89PNG':
content_type = 'image/png'
elif img_data[:4] == b'GIF8':
content_type = 'image/gif'
elif img_data[:4] == b'RIFF':
content_type = 'image/webp'
_logger.info("Serving image for line %d: %d bytes, %s", line_id, len(img_data), content_type)
# Set extension-appropriate filename
ext = content_type.split('/')[-1]
if ext == 'jpeg':
ext = 'jpg'
return Response(
img_data,
content_type=content_type,
status=200,
headers={
'Content-Disposition': f'inline; filename="{filename.rsplit(".", 1)[0]}.{ext}"',
'Cache-Control': 'no-cache',
},
)
except Exception as e:
_logger.error("Failed to serve variant image %d: %s", line_id, e)
return request.not_found()