I'm using a React web app and trying to upload a file to AWS S3.
I've tried everything both locally (localhost:3000
) and when deployed to production (Vercel serverless functions).
I first use a fetch to retrieve a presigned url for the file upload, which works perfectly:
module.exports = async (req, res) => {
let {fileName, fileType} = req.body;
const post = await s3.createPresignedPost({
Bucket: BUCKET_NAME,
Fields: {
key: fileName
},
ContentType: fileType,
Expires: 60
});
res.status(200).json(post);
Then, in the second fetch:
await fetch(url, {method: 'POST', body: formData}
I'm getting:
fetch has been blocked by CORS policy: No 'Access-Control-Allow-Origin'
I have set up the Permissions -> CORS json in the bucket configuration correctly:
[
{
"AllowedHeaders": [
"*",
"Content-*"
],
"AllowedMethods": [
"HEAD",
"GET",
"PUT",
"POST",
"DELETE"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": [
"*"
]
}
]
I also verified the bucket name in my code.
I've tried:
getPresignedUrl
& createPresignedPost
to generate the urlPUT
& POST
requestsContent-Type
, x-amz-acl
) in the fetch requestHEAD
, allowing different headers (like "Content-*"
)I've tried everything and went over dozens of articles (1, 2) and browsing through questions here - but it's still not working. Not locally and not in production.
After endless hours of digging into this, I found the issue.
The reason for the CORS error was that I didn't include the region
in the initial AWS.config.update
configuration setup.
Once I added the region
key, the CORS error was solved:
const AWS = require('aws-sdk');
AWS.config.update({
accessKeyId: 'XXXXX',
secretAccessKey: 'XXXXXX',
region: 'us-west-2', // Must be the same as your bucket
});
const s3Client = new AWS.S3();
It's really confusing and misleading that the error returned for not configuring the bucket region is CORS.