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?
Advertisement
Answer
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())