1

Update: my sense is that this a bug in the Serverless framework's support for WSGI applications because I can deploy the identical code to AWS using Zappa and it works.

I have this bit of Flask code that works fine when run locally using the Flask dev server. I can send POST requests to the local dev server and it all works, but generates an error when I send POST requests to the same app when deployed on AWS using the Serverless framework. I would greatly appreciate thoughts on this problem.

The relevant portion of the stack trace generated by PIL's Image.open() is this:

File "/var/task/app.py", line 30, in media
    img = Image.open(image)
  File "/var/task/PIL/Image.py", line 2590, in open
    % (filename if filename else fp))
OSError: cannot identify image file <FileStorage: 'clipart.png' ('image/png')>

Here's the code:

from flask import Flask, request
from PIL import Image
from io import BytesIO, StringIO
from werkzeug.utils import secure_filename


app = Flask(__name__)
app.debug=True


@app.route('/', methods=['GET', 'POST'])
def media():

    response = ""
    if request.method == 'POST':

        try:
            image = request.files['file']
            #  Variations tried with no difference:
            #  image = request.files['file'].read()
            #  image = request.files['file'].stream
            #  image = request.files['file'].stream.read()


            if isinstance(image, str):
                print("Trying to open the image with StringIO")
                img = Image.open(StringIO(image))

            elif isinstance(image, (bytes, bytearray)):
                print("Trying to open the image with BytesIO")
                img = Image.open(BytesIO(image))

            else:
                print("Trying to open the image without BytesIO or StringIO")
                img = Image.open(image)
                response = {}
                response['shape'] = (img.size[0], img.size[1])

        except Exception as e:
            print("An exception occured: {}".format(e))
            raise e

        else:
            print("Everything worked!")

    else:
        response = {"GET":"request"}

    return response
Raj
  • 3,791
  • 5
  • 43
  • 56
  • Did you package PIL package and uploaded it to AWS lambda? – GraphicalDot Mar 30 '20 at 14:31
  • Yes, because the Serverless framework does all of that for you. – Raj Mar 30 '20 at 14:38
  • If you have it behind API gateway this could be the problem. We couldn't get it to work if we uploaded multipart, when we use base64 str in json body it worked fine.(but you will need to decode it). Maybe this could help: https://stackoverflow.com/a/52725570/6555866 – Jan Giacomelli Mar 30 '20 at 14:54
  • It is indeed behind API Gateway, but I don't have the option to use base64 encoding because the Trix editor (which I am using on the front-end) uses multipart/form-data to POST files. I tried setting multipart/form-data in the binary types portion of the API Gateway console, but that didn't change anything. Thanks for the suggestion though. – Raj Mar 30 '20 at 15:03
  • has anyone solved this problem ? – 89n3ur0n Aug 20 '23 at 18:38

1 Answers1

0

I had the same issue. I solved it by adding multipart/form-data in the API gateway settings. enter image description here

Setting multipart/form-data in the Binay Media Settings allows the file to be actually written to the stream.

Thus should fix your problem too since I can see you have the same flow.

Also,do not forget to deploy the API again. Let me know if it does not work and add details if any.

89n3ur0n
  • 921
  • 11
  • 24