Next.js Functions


Using NEXT.js with Amazon S3: File Uploads and Cloud Storage

In today’s digital age, file uploads and cloud storage have become an integral part of web applications. Whether you’re building a simple blog or a complex e-commerce platform, handling file uploads and storage efficiently is crucial. NEXT.js, a popular React framework for building web applications, can be seamlessly integrated with Amazon S3, Amazon Web Services’ scalable object storage service. This powerful combination allows you to manage file uploads and cloud storage with ease, ensuring a smooth user experience and efficient data management.

Using NEXT.js with Amazon S3: File Uploads and Cloud Storage

In this comprehensive guide, we will explore how to use NEXT.js with Amazon S3 for file uploads and cloud storage. We’ll cover everything from setting up your environment to handling uploads and retrieving files from S3. Let’s dive in!

1. Prerequisites

Before we start, make sure you have the following prerequisites in place:

  • Node.js and npm: Ensure you have Node.js and npm installed on your system. You can download them from the official website.
  • Amazon S3 Account: You need an Amazon Web Services (AWS) account to use Amazon S3. If you don’t have one, sign up at the AWS Console.
  • AWS Access Key and Secret Key: Generate an AWS Access Key and Secret Key from the AWS Console by following these steps.
  • NEXT.js Project: Have a NEXT.js project set up and ready to go. If you’re new to NEXT.js, you can create a new project using the following command:
npx create-next-app my-next-app

Now that you have the prerequisites covered, let’s proceed with integrating NEXT.js and Amazon S3 for file uploads and cloud storage.

2. Setting Up Amazon S3

2.1. Create an S3 Bucket

The first step is to create an Amazon S3 bucket where you will store your uploaded files. Follow these steps:

  1. Log in to your AWS Console.
  2. Navigate to the S3 service.
  3. Click the Create bucket button.
  4. Provide a unique and meaningful name for your bucket.
  5. Choose the region where you want to create the bucket.
  6. Configure bucket settings according to your requirements. For most use cases, you can leave the default settings as they are.

Review your configurations and click the Create bucket button.

2.2. Configure Bucket Permissions

Once your bucket is created, you need to configure permissions to allow access to it. Here, we will create a simple public-read policy for the bucket. Keep in mind that this is just for demonstration purposes, and you should adjust permissions based on your application’s security requirements.

  1. Select the bucket you just created.
  2. Go to the Permissions tab.
  3. Click the Bucket Policy button.
  4. Add a policy similar to the following, replacing <your-bucket-name> with your actual bucket name:
    "Version": "2012-10-17",
    "Statement": [
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::<your-bucket-name>/*"

Click the Save button to apply the policy.

Your S3 bucket is now set up and configured with the necessary permissions. Next, we’ll integrate it into your NEXT.js application.

3. Integrating Amazon S3 with NEXT.js

3.1. Install Dependencies

In your NEXT.js project directory, install the required npm packages to work with Amazon S3. You’ll need the aws-sdk library to interact with S3 and multer for handling file uploads. Install them using the following command:

npm install aws-sdk multer

3.2. Configure AWS SDK

To interact with your S3 bucket, you need to configure the AWS SDK with your AWS Access Key and Secret Key. Create a new file called aws-config.js in your project’s root directory and add the following code:

const AWS = require('aws-sdk');

  accessKeyId: process.env.AWS_ACCESS_KEY_ID,
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
  region: process.env.AWS_REGION,

const s3 = new AWS.S3();

module.exports = s3;

Make sure to replace the placeholders (process.env.AWS_ACCESS_KEY_ID, process.env.AWS_SECRET_ACCESS_KEY, and process.env.AWS_REGION) with your actual AWS credentials. It’s a best practice to store sensitive information like access keys in environment variables for security reasons.

3.3. Create an Upload Route

Now, let’s create a route in your NEXT.js application to handle file uploads. Create a new file called upload.js in your pages/api directory. This will be an API route that accepts file uploads and stores them in your S3 bucket.

import multer from 'multer';
import { v4 as uuidv4 } from 'uuid';
import s3 from '../../aws-config';

const upload = multer({
  storage: multer.memoryStorage(),
  limits: {
    fileSize: 5 * 1024 * 1024, // 5MB file size limit

export const config = {
  api: {
    bodyParser: false,

export default async (req, res) => {
  try {
    // Upload file to S3
    const file = req.file;
    const key = `uploads/${uuidv4()}_${file.originalname}`;
    const params = {
      Bucket: process.env.AWS_BUCKET_NAME,
      Key: key,
      Body: file.buffer,
    await s3.upload(params).promise();

    // Return S3 file URL
    const fileUrl = `https://${process.env.AWS_BUCKET_NAME}${key}`;
    res.status(200).json({ url: fileUrl });
  } catch (error) {
    console.error('Error uploading file to S3:', error);
    res.status(500).json({ error: 'Failed to upload file to S3' });

This route uses multer to handle file uploads and stores the uploaded file in your S3 bucket. It generates a unique key for each uploaded file to avoid naming conflicts.

3.4. Create the File Upload Component

Now that you have the backend set up, create a file upload component in your NEXT.js application. You can create a new component called FileUpload.js in your components directory with the following code:

import { useState } from 'react';
import axios from 'axios';

const FileUpload = () => {
  const [selectedFile, setSelectedFile] = useState(null);
  const [uploading, setUploading] = useState(false);
  const [fileUrl, setFileUrl] = useState('');

  const handleFileChange = (e) => {

  const handleUpload = async () => {
    if (!selectedFile) return;

    const formData = new FormData();
    formData.append('file', selectedFile);

    try {
      const response = await'/api/upload', formData, {
        headers: {
          'Content-Type': 'multipart/form-data',
    } catch (error) {
      console.error('Error uploading file:', error);
    } finally {

  return (
      <input type="file" onChange={handleFileChange} />
      <button onClick={handleUpload} disabled={uploading}>
      {fileUrl && (
          <p>File uploaded successfully!</p>
          <img src={fileUrl} alt="Uploaded file" />

export default FileUpload;

This component allows users to select a file, upload it, and displays the uploaded file if the upload is successful.

3.5. Incorporate the File Upload Component

Now that you have created the FileUpload component, incorporate it into your NEXT.js application where needed. For example, you can add it to a page component or a form component to allow users to upload files.

import FileUpload from '../components/FileUpload';

const UploadPage = () => {
  return (
      <h1>Upload a File</h1>
      <FileUpload />

export default UploadPage;

3.6. Deploy Your NEXT.js Application

Once you have integrated Amazon S3 file uploads into your NEXT.js application, it’s time to deploy it to a hosting platform of your choice. Popular options include Vercel, Netlify, and AWS Amplify. Ensure that your deployment environment is properly configured with the AWS access keys and bucket name as environment variables to ensure seamless integration.

4. Retrieving Files from Amazon S3

Now that you’ve learned how to upload files to Amazon S3 using NEXT.js, you might also need to retrieve and display these files in your application. To do this, you can use the AWS SDK to interact with your S3 bucket and retrieve files based on their keys.

Here’s an example of how to retrieve a file from S3 and display it in your NEXT.js application:

import { useEffect, useState } from 'react';
import axios from 'axios';

const DisplayFile = () => {
  const [fileUrl, setFileUrl] = useState('');

  useEffect(() => {
    // Replace 'your-file-key' with the actual key of the file you want to retrieve
    const fileKey = 'your-file-key';

    // Make a GET request to your API route that retrieves the file from S3
    axios.get(`/api/getFile?fileKey=${fileKey}`).then((response) => {
  }, []);

  return (
      {fileUrl ? (
        <img src={fileUrl} alt="File from S3" />
      ) : (
        <p>File not found or loading...</p>

export default DisplayFile;

In the code above, we use an axios GET request to a route in your NEXT.js API (e.g., /api/getFile) to retrieve the file from S3 based on its key. Make sure to replace ‘your-file-key’ with the actual key of the file you want to retrieve. The retrieved file’s URL is then set in the component’s state and displayed in the UI.


Integrating NEXT.js with Amazon S3 for file uploads and cloud storage is a powerful combination that enables you to build robust web applications with efficient file management capabilities. In this guide, you’ve learned how to set up an S3 bucket, configure your NEXT.js project, create a file upload route, and build a file upload component. Additionally, we’ve touched on how to retrieve files from S3 for display in your application.

With this knowledge, you can enhance your web applications by seamlessly handling file uploads and cloud storage, providing a better user experience and efficient data management. As you continue to develop your projects, you’ll find that the integration of NEXT.js and Amazon S3 is a valuable asset for building modern web applications. Start experimenting and building your own applications today!

Previously at
Flag Argentina
time icon
Accomplished Senior Software Engineer with Next.js expertise. 8 years of total experience. Proficient in React, Python, Node.js, MySQL, React Hooks, and more.