ag1le
ag1le

Reputation: 11

Dynamically created JPG image using AWS Lambda service

I am trying to create a dynamically created graph as a JPG file that I could use in Alexa Skill standard cards as part of response. The following code creates a JPG image when I run it locally on my computer, when using browser with URL "http://localhost:5000/image.jpg".

from flask import send_file
from flask import Flask
from PIL import Image, ImageDraw
from io import BytesIO


app = Flask(__name__)
app.config['DEBUG'] = True


def serve_pil_image(pil_img):
    img_io = BytesIO()
    pil_img.save(img_io, 'JPEG', quality=70)
    img_io.seek(0)
    return send_file(img_io, mimetype='image/jpeg')

@app.route('/image.jpg')
def serve_img():
    size = (128,128)
    background = (128,128,55)
    xy = [(0,0),(10,10),(20,20),(30,12),(50,50),(70,9),(90,70)]

    img = Image.new('RGB',size,background)
    draw = ImageDraw.Draw(img)
    draw.line(xy, fill=128, width=5)
    return serve_pil_image(img)


if __name__ == '__main__':

    app.run(debug=True)

However, when I deploy the same code to AWS Lambda service using Zappa I am getting the following error message (from CloudWatch logs):

An error occurred during JSON serialization of response: 'utf8' codec can't decode byte 0xff in position 0: invalid start byte
Traceback (most recent call last):
File "/usr/lib64/python2.7/json/__init__.py", line 250, in dumps
sort_keys=sort_keys, **kw).encode(obj)
File "/usr/lib64/python2.7/json/encoder.py", line 207, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/usr/lib64/python2.7/json/encoder.py", line 270, in iterencode
return _iterencode(o, 0)
UnicodeDecodeError: 'utf8' codec can't decode byte 0xff in position 0: invalid start byte

Is there some configuration option to fix this problem? I haven't found any so far.

Upvotes: 1

Views: 1233

Answers (2)

David Salamon
David Salamon

Reputation: 2451

If you want to serve binary data (in this case Base64 images) through API Gateway, you need to set the following:

  1. In the Method Response of your method
    Set Content-Type as image/jpeg in HTTP 200 Status Response Header
  2. In the Integration Response of your method
    Set Content-Type as 'image/jpeg' in Header Mappings. Mind the quotes!
  3. With the AWS CLI, set contentHandling attribute to CONVERT_TO_BINARYon your Integration Response

Check to entire process in this great step-by step guide: https://stackoverflow.com/a/41434295/720665
(example is for a base64 encoded png image, but the gist of it is the same)

Upvotes: 1

pjz
pjz

Reputation: 43057

Binary Support is finally here! You should look at it and try again.

Upvotes: 1

Related Questions