Uploading Files to Amazon S3 in a Next.js Application Using AWS SDK v3
Tags: nextjs, javascript, aws, awsfileuploadingnodejs
Published: 2024-06-26 03:44:02

# Uploading Files to Amazon S3 in a Next.js Application Using AWS SDK v3

In this tutorial, we will walk through how to upload files to Amazon S3 in a Next.js application using the AWS SDK for JavaScript (v3). We will ensure that the files are served securely over HTTPS using the appropriate URL format.

## Prerequisites

- Basic knowledge of Next.js
- An AWS account
- Node.js installed on your machine

## Step 1: Set Up Your S3 Bucket

### Create an S3 Bucket

1. Go to the [AWS Management Console](https://aws.amazon.com/console/).
2. Navigate to the S3 service and create a new bucket.
3. Choose a unique name and a region closest to your users.
4. Set up the bucket to allow public read access for simplicity (you can refine the permissions later).

### Set Bucket Policy and CORS

#### Bucket Policy

Add the following bucket policy to allow public read access:

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

#### CORS Configuration

Configure your bucket with the following CORS rules:

```xml
<CORSConfiguration>
  <CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>HEAD</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedMethod>DELETE</AllowedMethod>
    <AllowedHeader>*</AllowedHeader>
  </CORSRule>
</CORSConfiguration>
```

## Step 2: Set Up AWS SDK v3

### Install AWS SDK v3

In your Next.js project, install the required AWS SDK packages:

```bash
npm install @aws-sdk/client-s3 @aws-sdk/lib-storage
```

## Step 3: Create an API Route for File Upload

Create an API route in your Next.js application to handle file uploads to S3.

### Create `/src/app/api/upload/route.js`

```javascript
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
import { Upload } from '@aws-sdk/lib-storage';

const s3Client = new S3Client({
  region: process.env.AWS_REGION,
  credentials: {
    accessKeyId: process.env.AWS_ACCESS_KEY_ID,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
  },
});

export async function POST(req) {
  try {
    const { file } = await req.json();
    const base64Data = Buffer.from(file.replace(/^data:image\/\w+;base64,/, ""), 'base64');
    const type = file.split(';')[0].split('/')[1];

    const params = {
      Bucket: process.env.AWS_BUCKET_NAME,
      Key: `uploads/${Date.now().toString()}.${type}`,
      Body: base64Data,
      ContentEncoding: 'base64',
      ContentType: `image/${type}`,
    };

    const upload = new Upload({
      client: s3Client,
      params: params,
    });

    const data = await upload.done();

    // Generate the URL in the desired format
    const url = `https://s3.amazonaws.com/${params.Bucket}/${params.Key}`;

    return new Response(JSON.stringify({ url: url }), {
      status: 200,
      headers: { 'Content-Type': 'application/json' },
    });
  } catch (error) {
    return new Response(JSON.stringify({ error: error.message }), {
      status: 500,
      headers: { 'Content-Type': 'application/json' },
    });
  }
}
```

## Step 4: Create a File Upload Component

Create a file upload component to allow users to upload files from the client-side.

### Create `/src/components/FileUpload.js`

```javascript
'use client';

import { useState } from 'react';

const FileUpload = () => {
  const [file, setFile] = useState(null);
  const [message, setMessage] = useState('');

  const handleChange = (event) => {
    setFile(event.target.files[0]);
  };

  const handleSubmit = async (event) => {
    event.preventDefault();

    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onloadend = async () => {
      const base64data = reader.result;
      const response = await fetch('/api/upload', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ file: base64data }),
      });

      if (response.ok) {
        const data = await response.json();
        setMessage(`File uploaded successfully! File URL: ${data.url}`);
      } else {
        setMessage('File upload failed.');
      }
    };
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="file" onChange={handleChange} />
      <button type="submit">Upload</button>
      {message && <p>{message}</p>}
    </form>
  );
};

export default FileUpload;
```

## Step 5: Use the Component in Your Page

Include the `FileUpload` component in one of your Next.js pages.

### Create `/src/app/page.js`

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

export default function Home() {
  return (
    <div>
      <h1>Upload a File to S3</h1>
      <FileUpload />
    </div>
  );
}
```

## Step 6: Configure Environment Variables

Ensure you have the necessary environment variables set up in your Next.js project. Create a `.env.local` file in the root of your project if it doesn't exist:

### Create `.env.local`

```plaintext
AWS_ACCESS_KEY_ID=your-access-key-id
AWS_SECRET_ACCESS_KEY=your-secret-access-key
AWS_REGION=your-region
AWS_BUCKET_NAME=your-bucket-name
```

Replace `your-access-key-id`, `your-secret-access-key`, `your-region`, and `your-bucket-name` with the actual values from your AWS account.

## Step 7: Restart Your Development Server

Make sure to restart your Next.js development server to apply the new environment variables.

## Conclusion

By following these steps, you should be able to upload files from your Next.js application to an S3 bucket using the AWS SDK for JavaScript (v3). The files will be served securely via HTTPS using the correct URL format. Happy coding!