Uploading Files via preSignedUrl to S3 buckets directly on AWS in JavaScript

Content-Type is an empty string, a wrong implementation

This post is about if you are going to do uploading files in JavaScript via preSignedUrl to S3 bucket directly on modern browsers, then something you should know before doing it.

1. There is a preflight (OPTION) request before your PUT request.

This is a basic know-how you should know. A non-simple request will send a preflight request to check the request is safe or not for a CORS (Cross-origin resource sharing) request.

And it's interesting that AWS had a bug with it a few years ago.
draganbajcic,

Thank you, and everybody else, for the report. You are correct that pre-signed requests returning an error on the initial OPTIONS request. We are working on this issue and expect to add this support shortly. I don't have a timeline for the availability of the change but I will update this thread with more information when I have that. If you have any follow up questions let me know.

Thanks,
Carl

2. Configure your S3 bucket's Response headers to allow CORS.

For modern browsers, CORS requests are restricted in some cases. So, in short, you need to make your S3 bucket has Access-Control-Allow-Origin related headers in its response. You can do it easily in a console here, https://docs.aws.amazon.com/AmazonS3/latest/UG/EditingBucketPermissions.html

3. Content-Type is one important parameter to generate the preSignedUrl.

I took some time to validate the answer and then made a request to ask our colleagues to correct the implementation that they missed putting Content-Type as a parameter to generate the preSignedUrl to fix the issue.

If you send the request with different Content-Type from the content type you used to generate the preSignedUrl in your request's Header. You will get the following error response.

So...

There is no any HARD tech implementation here. The whole flow is "getting the preSignedUrl" and "Use it as target URL to upload files and putting correct Content-Type in your header". That's it.