🎉 Next S3 Uploader is now in beta! Please report any bugs or issues on GitHub.
Introduction

Next.js S3 Uploader

Next S3 Uploader is a utility package designed to simplify file uploads in Next.js applications. With this package, you can seamlessly integrate file upload functionality, track upload progress, and generate secure pre-signed URLs for Amazon S3 and compatible services like MinIO.

Key Benefits

  • Effortless Integration: Quickly add file upload capabilities to your Next.js projects.
  • Custom Hook: Utilize the useS3FileUpload hook for easy file upload management.
  • Security First: Securely upload files with pre-signed URLs for Amazon S3 or MinIO.
  • Real-time Progress: Keep users informed with real-time upload progress tracking.
  • Versatile Configuration: Tailor settings for both S3 and MinIO services to suit your needs.
⚠️

This package is currently in beta and is not recommended for production use.

This is to be used in the app directory of Next.js projects. It is not intended for use in the pages directory.

Get Started

To begin using Next S3 Uploader, follow these simple installation steps:

npm i next-s3-uploader

Configuration

S3 Policy for Public Bucket

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicRead",
      "Effect": "Allow",
      "Principal": "*",
      "Action": ["s3:GetObject"],
      "Resource": ["arn:aws:s3:::your-bucket-name/*"]
    }
  ]
}

Usage

Next.js App Directory Frontend

app/upload/page.tsx
"use client";
 
import React from "react";
import { useS3FileUpload } from "next-s3-uploader";
 
function UploadPage() {
  const { uploadedFiles, uploadFiles } = useS3FileUpload({
    multiple: true,
    maxFiles: 10,
    maxFileSize: 10 * 1024 * 1024, // 10MB limit
  });
 
  const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const files = e.target.files;
    if (files && files.length > 0) {
      await uploadFiles(files, undefined);
    }
  };
 
  return (
    <div>
      <h1>File Upload to Amazon S3</h1>
      <input
        title="Upload File"
        type="file"
        accept="image/*"
        multiple
        onChange={handleFileChange}
      />
      <div>
        {uploadedFiles.map((file, index) => (
          <div key={index}>
            <p>File Key: {file.key}</p>
            <p>Status: {file.status}</p>
            <p>Progress: {file.progress}%</p>
            <p>Time Left: {file.timeLeft || "Calculating..."}</p>
            {file.status === "success" && (
              <img src={file.url} alt={`Uploaded File ${index}`} />
            )}
          </div>
        ))}
      </div>
    </div>
  );
}

Next.js API Directory Backend

app/api/s3upload.js
import { createS3Client, generatePresignedUrls } from "next-s3-uploader";
 
export async function POST(req) {
  try {
    const { keys } = await req.json();
 
    // Configure AWS S3 client
    const s3Client = createS3Client({
      provider: "aws", // Amazon S3 provider
      region: "us-east-1", // Specify the appropriate AWS region
      credentials: {
        accessKeyId: "YOUR_ACCESS_KEY_ID", // Your AWS access key ID
        secretAccessKey: "YOUR_SECRET_ACCESS_KEY", // Your AWS secret access key
      },
    });
 
    // Generate pre-signed URLs
    const bucket = "your-bucket-name";
    const prefix = `userId/images/`;
    const urls = await generatePresignedUrls(s3Client, keys, bucket, prefix);
 
    return new Response(JSON.stringify(urls), { status: 200 });
  } catch (error) {
    console.error("Error processing the request:", error);
    return new Response("Internal Server Error", { status: 500 });
  }
}