DEV Community

Cover image for Upload Files to Amazon S3 Using Node.js, Express, and AWS SDK v3
Amit Kumar
Amit Kumar

Posted on

Upload Files to Amazon S3 Using Node.js, Express, and AWS SDK v3

Uploading files is a feature you'll eventually need in almost every web application—whether it's profile pictures, PDFs, invoices, or media files. Instead of storing uploads on your server, Amazon S3 provides a reliable, scalable, and highly durable solution.

In this tutorial, we'll build a simple REST API using Node.js, Express, Multer, and AWS SDK v3 that uploads files directly to an Amazon S3 bucket.

Prerequisites

Before you begin, make sure you have:

  • Node.js 18 or later
  • An AWS account
  • An Amazon S3 bucket
  • An IAM user with programmatic access
  • AWS Access Key ID and Secret Access Key

Step 1: Create a New Project

mkdir s3-upload-api
cd s3-upload-api

npm init -y
Enter fullscreen mode Exit fullscreen mode

Install the required packages:

npm install express multer dotenv uuid @aws-sdk/client-s3
Enter fullscreen mode Exit fullscreen mode

Step 2: Configure Environment Variables

Create a .env file.

AWS_REGION=ap-south-1
AWS_ACCESS_KEY_ID=YOUR_ACCESS_KEY
AWS_SECRET_ACCESS_KEY=YOUR_SECRET_KEY
AWS_BUCKET_NAME=YOUR_BUCKET_NAME
PORT=3000
Enter fullscreen mode Exit fullscreen mode

Create a .gitignore file.

node_modules
.env
Enter fullscreen mode Exit fullscreen mode

Step 3: Configure the Amazon S3 Client

import { S3Client } from "@aws-sdk/client-s3";

const s3 = new S3Client({
  region: process.env.AWS_REGION,
  credentials: {
    accessKeyId: process.env.AWS_ACCESS_KEY_ID,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
  },
});
Enter fullscreen mode Exit fullscreen mode

Step 4: Configure Multer

We'll use memory storage so files are uploaded directly to Amazon S3.

import multer from "multer";

const upload = multer({
  storage: multer.memoryStorage(),
});
Enter fullscreen mode Exit fullscreen mode

Step 5: Create the Upload Endpoint

import { PutObjectCommand } from "@aws-sdk/client-s3";
import { v4 as uuid } from "uuid";

app.post("/upload", upload.single("file"), async (req, res) => {
  try {
    const filename = `${uuid()}-${req.file.originalname}`;

    await s3.send(
      new PutObjectCommand({
        Bucket: process.env.AWS_BUCKET_NAME,
        Key: filename,
        Body: req.file.buffer,
        ContentType: req.file.mimetype,
      })
    );

    res.json({
      success: true,
      filename,
    });
  } catch (error) {
    console.error(error);

    res.status(500).json({
      success: false,
      message: "Upload failed",
    });
  }
});
Enter fullscreen mode Exit fullscreen mode

Step 6: Start the Server

npm start
Enter fullscreen mode Exit fullscreen mode

Step 7: Test with Postman

Send a POST request to:

POST http://localhost:3000/upload
Enter fullscreen mode Exit fullscreen mode

Select:

Body → form-data

Key: file
Type: File
Enter fullscreen mode Exit fullscreen mode

Choose any image or document and click Send.

Example response:

{
  "success": true,
  "filename": "4c6ddcf2-profile.png"
}
Enter fullscreen mode Exit fullscreen mode

You should now see the uploaded file in your Amazon S3 bucket.

Common Errors

AccessDenied

Your IAM user doesn't have permission to upload objects. Make sure the user has the s3:PutObject permission.

NoSuchBucket

Verify the bucket name and AWS Region.

InvalidAccessKeyId

Check that your AWS credentials are correct.

Next Steps

Once the basic upload API is working, you can enhance it by:

  • Supporting multiple file uploads
  • Generating pre-signed URLs
  • Validating file type and size
  • Uploading directly from a React application
  • Using CloudFront for faster content delivery
  • Organizing uploads into folders

Further Reading

If you'd like to understand the concepts behind Amazon S3 before building production applications, these resources may help:

Conclusion

Building a file upload API with Node.js and Amazon S3 is straightforward once you understand the basic workflow. Using Express, Multer, and the AWS SDK v3, you can create a scalable upload service in just a few steps. From here, you can add authentication, pre-signed URLs, image processing, or integrate the API into your frontend application.

If you've implemented file uploads differently or have tips for improving this approach, feel free to share them in the comments.

Top comments (0)