0

I have an HTML form (implemented in Flask) for uploading files. And I want to store the uploaded files directly to S3.

The relevant part of the Flask implementation is as follows:

@app.route('/',methods=['GET'])
def index():
    return '<form method="post" action="/upload" enctype="multipart/form-data"><input type="file" name="files" /><button>Upload</button></form>'

I then use boto3 to upload the file to S3 as follows:

file = request.files['files']
s3_resource = boto3.resource(
    's3',
     aws_access_key_id='******',
     aws_secret_access_key='*******')

bucket = s3_resource.Bucket('MY_BUCKET_NAME')

bucket.Object(file.filename).put(Body=file)

file is a werkzeug.datastructures.FileStorage object.

But I get the following error when uploading the file to S3:

botocore.exceptions.ClientError: An error occurred (BadDigest) when calling the PutObject operation (reached max retries: 4): The Content-MD5 you specified did not match what we received.

How can I upload the file to S3?

John Rotenstein
  • 203,710
  • 21
  • 304
  • 382
Saurabh Sharma
  • 776
  • 4
  • 13
  • 40

1 Answers1

3

Since you are using Flask web framework, the file variable is of type werkzeug.datastructures.FileStorage.

I think the problem is that the put() method expects a byte sequence or a file-like object as its Body argument. So, it does not know what to do with the Flask's FileStorage object.

A possible solution could be to use file.read() to get a sequence of bytes and then pass it to put():

bucket.Object(file.filename).put(Body=file.read())
SergiyKolesnikov
  • 6,399
  • 2
  • 23
  • 42
  • Yuppp!!! its working. Now file is getting stored in to S3 bucket. but when I open that its blank.... image is not appearing, it seems like file not written properly. and its size is showing `0B` – Saurabh Sharma Feb 15 '20 at 13:38
  • This may be helpful https://stackoverflow.com/questions/40336918/how-to-write-a-file-or-data-to-an-s3-object-using-boto3 – SergiyKolesnikov Feb 16 '20 at 08:03