Search code examples
pythonrestamazon-s3chalice

What is best practice to have client upload image to S3 bucket via Chalice?


I am using the Chalice framework to create an API service. My users need to upload an image and then I need to save the image to an s3 bucket.

How should the user upload the image to my endpoint and what should my endpoint do once it receives it?

This is my thought process so far:

BUCKET = <bucket_name>    
@app.route('/n_number_search/', methods=['POST'])
    def n_number_search():
        body = app.current_request.raw_body
        s3_client.upload_file(body, BUCKET, UUID_file_name)
        return Response(body=f'upload successful: {}', status_code=200,
                        headers={'Content-Type': 'text/plain'})

This is not working. I have reviewed the way to do this in flask but the syntax is a slightly different as flask has the request.files attribute.


Solution

  • One good practice is to use a pre-signed URL. Here's the process in high-level:

    1. Your client requests permission to upload a file
    2. Your Lambda function is triggered, generates the pre-signed URL (make sure the Lambda has necessary permissions to the S3 bucket) and respond to the client
    3. The client takes the pre-signed URL and uploads the file directly to S3;

    Advantages are:

    • Reduces network latency by not uploading twice (one time to Lambda, second to S3);

    • Reduces your Lambda bill: it's much faster - thus cheaper - to generate a pre-signed URL than to wait for an upload;

    • Eliminates upload failure: Lambda timeout is 5 minutes and will fail if the upload takes more time (which may happen if the file is too big or your user is in a bad internet connection);