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
privateACL 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.
