How to Upload Files in Express.js to AWS S3 Using AWS SDK v3 and Multer
Uploading files to AWS S3 is a common task in many backend applications. In this tutorial, you'll learn how to build a clean Express.js API using multer for handling file uploads, and AWS SDK v3 with PutObjectCommand
to upload files directly to S3.
📦 What We'll Use
Express.js
– Web framework for Node.jsmulter
– Middleware to handle file uploads@aws-sdk/client-s3
– AWS SDK v3 for S3dotenv
– Manage environment variables
📁 Folder Structure
- server.js
- upload/
- s3Client.js
- .env
🔧 Step 1: Install Dependencies
pnpm add express multer dotenv @aws-sdk/client-s3
🔐 Step 2: Create Your .env File
AWS_ACCESS_KEY=your-access-key
AWS_SECRET_KEY=your-secret-key
AWS_REGION=us-east-1
AWS_BUCKET=your-bucket-name
☁️ Step 3: Configure the S3 Client (upload/s3Client.js)
const { S3Client } = require("@aws-sdk/client-s3");
const dotenv = require("dotenv");
dotenv.config();
const s3 = new S3Client({
region: process.env.AWS_REGION,
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY,
secretAccessKey: process.env.AWS_SECRET_KEY
}
});
module.exports = s3;
🚀 Step 4: Express Server with File Upload (server.js)
const express = require("express");
const multer = require("multer");
const { PutObjectCommand } = require("@aws-sdk/client-s3");
const s3 = require("./upload/s3Client");
const dotenv = require("dotenv");
dotenv.config();
const app = express();
// Multer memory storage
const storage = multer.memoryStorage();
const upload = multer({ storage });
app.post("/upload", upload.single("file"), async (req, res) => {
const file = req.file;
if (!file) return res.status(400).json({ message: "No file uploaded" });
const params = {
Bucket: process.env.AWS_BUCKET,
Key: `${Date.now()}-${file.originalname}`,
Body: file.buffer,
ContentType: file.mimetype,
ACL: "public-read" // or use "private"
};
try {
const command = new PutObjectCommand(params);
await s3.send(command);
const url = `https://${process.env.AWS_BUCKET}.s3.${process.env.AWS_REGION}.amazonaws.com/${params.Key}`;
res.status(200).json({ message: "File uploaded", url });
} catch (error) {
console.error("Upload Error:", error);
res.status(500).json({ message: "Upload failed", error: error.message });
}
});
app.listen(5000, () => console.log("Server running on port 5000"));
🧪 Testing the API
You can test this endpoint using Postman or any REST client:
- URL:
POST http://localhost:5000/upload
- Body Type:
form-data
- Key:
file
, Type: File, Upload any image or PDF
✅ Sample Output
{
"message": "File uploaded",
"url": "https://your-bucket-name.s3.us-east-1.amazonaws.com/1690641920000-image.png"
}
💡 Tips & Best Practices
- ✅ Use UUIDs for more secure filenames
- ✅ Use
private
ACL and generate signed URLs for access control - ✅ Validate MIME types to avoid unwanted file uploads
- ✅ Add size limits in Multer config to prevent abuse
🧵 Final Thoughts
Using AWS SDK v3 gives you a modular and modern approach to interacting with AWS services. Combined with multer
and Express
, you can build highly scalable and stateless file upload APIs ready for production.
Next step? Hook this into your user profile image uploads, admin panel, or client-facing file uploader.
0 Comments