Uploading files to AWS s3
For you to be able to upload to AWS S3
and sync your database
with your S3
bucket, you need to set up S3 Bucket
and SNS
.
Let's get started.
Configuration
- Sign in or sign up on AWS
- Go to your AWS console
- Account menu in the upper-right (has your name on it) then click
Security Credentials
- Create your
access key
- Update your
.env.local
.env.local
AWS_ACCESS_KEY_ID= # Your AWS Key ID
AWS_SECRET_ACCESS_KEY= # Your AWS ACCESS Key
- Update
config.ts
/src/utils/config.ts
const config = {
//...
// AWS S3 configuration for storing media files.
aws: {
region: "my-bucket-region", // AWS region where the S3 bucket is hosted.
bucketName: "my-bucket-name", // Name of the S3 bucket.
hostname: "my-bucket-name.s3.my-bucket-region.amazonaws.com", // Hostname for accessing the bucket.
bucketUrl: "https://hostname", // Full URL to the S3 bucket.
},
// Configuration for file uploads.
upload: {
imageExtensions: [".jpg", ".jpeg", ".png", ".gif", ".webp"], // Allowed image file extensions.
videoExtensions: [".mp4"], // Allowed video file extensions.
},
};
SNS (Simple Notification Service)
SNS
is a service offered by AWS
one
of its features is notify you when an s3 object is created/updated/deleted.
We will use it so when we upload or delete any s3 object in the admin dashboard our database will update itself based on the actions we take.
You can think of it as a webhook, in fact I have added the API route for
handling these notifications under /api/webhooks/s3
Testing Locally
Because SNS does not work with localhost we need a service that will act
as a proxy to redirect traffic from AWS
to localhost.
The service I have used is called ngrok
Setup ngrok (skip for production)
- Sign up here
- On successful sign up you should be able to access their guide here
- Choose your OS if not auto selected and follow their installation steps
- Then in your terminal/cmd run
ngrok http http://localhost:3000
Setup SNS
- Go to your AWS console
- Enter
SNS
in the search bar and select it - Create a topic by giving it a name and make sure the type is
Standard
- Click
Create Topic
then open it if it didn't automatically - Copy the topic (ARN) and Topic owner then click
Edit
- Expand
Access Policy
and enter this policy
Access policy
{
"Version": "2008-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "s3.amazonaws.com"
},
"Action": "sns:Publish",
"Resource": "your_topic_arn_here",
"Condition": {
"StringEquals": {
"AWS:SourceAccount": "topic_owner_number"
}
}
}
]
}
- Save changes
- Under
Subscriptions
clickCreate subscription
- Select Topic ARN you just created and the
https
Protocol - For localhost type the
URL
you got fromngrok
and for production your app url followed by/api/webhooks/s3
- e.g.
https://your_domain/api/webhooks/s3
- e.g.
- Click create subscription and then wait for your subscription status to become
Confirmed
You can repeat steps 7-10 for both localhost and production
Update the S3 SNS logic
You can find the S3 SNS under src/app/api/webhooks/s3/route.ts
feel free to explore.
Setup AWS S3 bucket
- Go to your AWS console
- Create S3 bucket by typing
s3
in the search bar and select it - Click
Create bucket
- Pick a name for your bucket and uncheck
Block all public access
then clickCreate bucket
- Open your new bucket and click on
Properties
tab then copy the bucket(ARN)
code (keep it aside you will need it later)- Click on
Create event notification
- Pick a name
- Add a prefix
media/
(highly recommended so you can manually update your s3 to this bucket without triggering notification on the dashboard upload folder and causing a crash) - Check
All object create events
andAll object removal events
- Select SNS Topic as
Destination
- Choose the
SNS
topic that you created earlier. - Save the changes
- Click on
- Click on
Permissions
tab and Edit theBucket policy
and enter this policy instead to allow public access to view s3 objects then save
Bucket policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "paste_your_ARN_here/media/*" # only allow public access to /media folder in the s3 bucket
}
]
}
Note
If you decide to update the default upload folder name /media
make sure to
also update the Resource
path in the bucket policy
- Edit
Cross-origin resource sharing (CORS)
and enter these rules then save
Cross-origin resource sharing (CORS)
[
{
"AllowedHeaders": [
"Authorization",
"x-amz-date",
"x-amz-content-sha256",
"content-type"
],
"AllowedMethods": [
"GET",
"PUT",
"POST"
],
"AllowedOrigins": [
"http://localhost:3000",
"https://your_app_domain"
],
"ExposeHeaders": [
"ETag",
"Location"
],
"MaxAgeSeconds": 3000
},
{
"AllowedHeaders": [],
"AllowedMethods": [
"GET"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": [],
"MaxAgeSeconds": 3000
}
]
🎉 S3 and SNS are now ready! Start by testing uploading under /dashboard