How to Upload Files in Express.js Using Multer and Upload to AWS S3

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.js
  • multer – Middleware to handle file uploads
  • @aws-sdk/client-s3 – AWS SDK v3 for S3
  • dotenv – 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.

Post a Comment

0 Comments