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:
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user