Uploading files to AWS S3 client side | NodeJS and ReactJS/NextJS
How to upload files to AWS S3 directly from client side using NodeJS ReactJS and NextJS with sample code.
Uploading static files has become a huge part of web development over the years with social media, e-commerce, and dashboard-y sites. One of the huge problems with uploading static media is that we need to eventually store it in some more persistent place like a cloud storage platform like AWS S3, which is a common choice among developers.
So in this article, I will be covering how to upload static files to AWS S3 directly from the client-side application (ReactJS in my example). Now before we begin, let's be clear. This approach requires a backend server like NodeJS, you can also use something like AWS Lambda but I personally found it a little more tedious than creating a simple backend app in NodeJS, you can be creative and use NextJS API Routes as well.
To begin with:
Creating a pre-signed URL for our upload in NodeJS.
async function createPresignedUploadUrl(fileName: string, fileType: string) {
const params = {
Bucket: process.env.AWS_BUCKET_NAME,
Key: fileName,
Expires: 60,
ContentType: fileType,
};
const preSingedUrl = await s3.getSignedUrlPromise("putObject", params);
return { preSingedUrl };
}
This would give you a pre-signed URL where you can upload your files.
Next step would be passing this to your frontend done most commonly using REST APIs and then you can send a XHR request to the URL using the code below as reference.
Frontend code | NextJS/ReactJS
const getPreSignedUrl = async (e: any) => {
e.preventDefault();
if (e.dataTransfer) {
e.target.files = e.dataTransfer.files;
}
const file = e.target.files[0];
// Send Request to get the presigned URL
// Your Logic
// Call the uploadToS3 function
uploadToS3(preSignedUrl, file);
};
const uploadToS3 = async (preSignedUrl: string, file: any) => {
// XHR request with file progress
const xhr = new XMLHttpRequest();
xhr.open("PUT", preSignedUrl, true);
xhr.setRequestHeader("Content-Type", file.type);
xhr.upload.addEventListener("progress", (e) => {
// You can add your progress bar animation code here.
});
xhr.addEventListener("load", async () => {
if (xhr.status === 200) {
alert("file upload completed");
} else {
alert("Could not upload file.");
}
});
xhr.addEventListener("error", () => {
alert("Could not upload file.");
});
xhr.addEventListener("abort", () => {
alert("Upload aborted.");
});
xhr.send(file);
return;
};
This was a short article that I was always looking for this problem. Please support me by sharing this article with your friends and colleagues 😊