I was working on uploading and downloading a file to S3 bucket using pre-signed URLs.I came across these two methods generate_presigned_url('put_object')
and generate_presigned_post
.
What is the difference between these two methods?
# upload a file to a bucket with generate_presigned_url with put object
s3_client.generate_presigned_url('put_object',
Params= {"Bucket": "BUCKET_NAME",
"Key": "OBJECT_KEY"},
ExpiresIn=3600)
# upload a file to a bucket using presigned post
s3_client.generate_presigned_post(Bucket="BUCKET_NAME",
Key="OBJECT_PATH",
ExpiresIn=3600)
Could someone please explain the difference between both?
If we have generate_presigned_post
why was there a generate_presigned_url
method with put_object
for uploading in the first place.
Note : I know that generate_presigned_post
is the recommended method for file uploads and I have used the same. However, there is no clear documentation on the difference between these methods.
This is an extended version of @jellycsc's comment. I had posted the same query to aws support as well. I got the below answer from them.
More detailed explanation is given here
Posting here as it could be useful for someone.
What is the difference between these two methods?
generate_presigned_post()
is more powerful because of the POST Policy feature. The POST Policy is simply conditions you set when creating the presigned POST. Using it, you can allow certain MIME types and file extensions, allow multiple files to be uploaded with a given prefix, restrict the file size, and more, which is not possible in generate_presigned_url()
Please note that both the methods can be used to fulfill the same goal, i.e provide controlled way for users to upload files directly to S3 buckets. The process is also the same for both as the backend needs to sign the request after validating that the user is authorized then the browser sends the file directly to S3.
Differences:
URLStructure:
PUT URLs encode everything in the URL itself as there is nothing else communicated back to the client. This means fewer variables can be customized.
POST URLs use multiple fields for different kinds of information. The signing algorithm returns a list of fields along with the URL itself and the client must send those to S3 as well while accessing the presigned URL.
While PUT URLs provide a destination to upload files without any other required parts, POST URLs are made for forms that can send multiple fields. However, their usage is not limited to forms.
Content Type
For PUT URLs the signing must be done for a specific content type. That means you either hardcode a content type on the backend, for example, application/xml if you want to allow users to upload XML documents, or the client must send the desired content type as part of the signing request.
For POST URLs the policy supports a prefix constraint as well as an exact match.
Content-Length:
In case of PUT URLs, you have no control over the size of the uploaded file.
For POST URLs you can set an allowed range in the policy.
Sample presigned post in python:
response = s3_client.generate_presigned_post(Bucket="BUCKET_NAME",
Key="S3KEY",
Fields={"Content-Type": "image/jpg"},
Conditions=["starts-with", "$Content-Type", "image/"],
ExpiresIn=3600)