Upload Files to AWS S3 securely from FrontEnd
3 min read
•
Jan 9, 2026
Hi there! Welcome to my blog, this is Alan.
Today, I’m going to share with you an approach of uploading files to aws s3 from front-end directly and securely, instead of the files goes to your server first, and then your server uploads files to s3.
If this is your current one:
Press enter or click to view image in full size

Then this is a new better one:
Press enter or click to view image in full size

Before I take you through implementation steps, let’s understand why we should do that:
For the first one, files -> server -> s3:
Pros:
- You can do validation as much as you want: name, file size, file content, etc… before storing it.
- You can check authentication and authorization
Cons:
- Heavy workload on the server if a lot of users upload multiple files simultaneously
- Consume a lot of bandwidth.
- Cost increases, because you have to scale the server
For the second one, files -> s3:
Pros:
- Scalability, as much as AWS s3 can handle, you don’t have to worry.
- Spend 1/2 bandwidth compare to the first one
- Fast, because AWS infrastructure.
- Remove heavy workload from your server.
Cons:
- Validation is limited
- Authentication, but not authorization.
The Cons of the second one can be fixed easily by when your backend pulls files from s3 to progress, it can do validations and check authorization.
Are you exciting to implement it? Let’s do it.
To save time, I have prepared a project for it using NextJS which is a great great React framework.
After pulling it, you will need:
- Change .dev.env to .env and update values in it. I think you know where to find those values.
- Set up credentials file for aws (you can google or leave a comment if you don’t know)
Use this command to spin up the project:
1npm run dev
You will see a really simple UI of file upload 😂:
Press enter or click to view image in full size

Now we go to the main part, upload file. So how does that work?
We will have 2 steps:
- FE will call an api on our server to generate preSignedUrl: the api will use AWS SDK to get preSignedUrl from AWS
- FE uploads file to that preSignedUrl which means the file goes straight to the AWS.
Open the src/pages/api/get-upload-url.ts: this is the api generating preSignedUrl for the upload. You can see I have another function for updating the CORS, so if you encounter CORS issue, you can uncomment and run it to fix.
Open the src/pages/index.tsx, you’ll see 2 functions:
- onSubmit: this one to send file info to the api and get the preSignedUrl
- uploadToUrl: after having result from onSubmit, this one will push the real file to the preSignedUrl.
To make the preSignedUrl more secure, you can add more configuration to PutObjectCommand:
- Expires: always recommended
- ContentMD5: ensure uploading file is matched with the original file, not modified or corrupted.
- And more, you can read here.
This approach is simple yet efficient. Why don’t you give it a try? cut the cost and level up your upload process.
Thanks for reading!