How to Upload Files to Amazon S3 with React and AWS SDK
Tags: aws, react, s3, javascript
Published: 2024-03-04 15:54:14

# INTRODUCTION

Have you ever needed to upload files from your React application to the cloud?

[Amazon S3 (Simple Storage Service)](https://aws.amazon.com/s3/) provides a robust and scalable solution for storing and managing various file types. 

Using the [AWS SDK](https://www.npmjs.com/package/aws-sdk), this article shows how to build a [React](https://react.dev/) application that allows users to upload files to S3. 

In the article, you'll learn how to handle file selection, validate file types, and handle the upload process with error handling. 

By the end, you'll have a basic understanding of integrating file uploads to S3 with React and AWS.

# Prerequisite:

- Basic understanding of React and JavaScript.
- An AWS account and access credentials to configure the S3 connection.

# Getting Started

## Creating S3 Bucket

The first thing to do is start by creating an S3 bucket. Log in to the AWS S3 console and follow the instructions to create a new bucket, as shown in the image below.


![Create Bucket](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8jjca9mzxy0834s4a6hm.png)

## Making the files publicly accessible


Next is to edit the bucket policy to make the file publicly accessible. 

Here's how:

- Open the bucket: Go to the AWS S3 console and navigate to your specific bucket.
- Access permissions: Click on the 'Permissions' tab.
- Edit policy: Locate the 'Bucket policy' section and click the 'Edit Policy' button.
- Paste JSON code: Copy and paste the following JSON code into the policy editor.
```javaScript
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicListGet",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:List*",
                "s3:Get*"
            ],
            "Resource": [
                "arn:aws:s3:::YOUR_BUCKET_NAME",
                "arn:aws:s3:::YOUR_BUCKET_NAME/*"
            ]
        }
    ]
}

```
- Save changes: Review the policy and click 'Save'.


The policy above makes all objects in the S3 bucket named _YOUR_BUCKET_NAME_ publicly accessible. Anyone online can list and download all files in the bucket and its subfolders. 

> The policy should be used cautiously as it can be a security risk.

## Editing CORS Policy

Now, you must enable **Cross-origin resource sharing (CORS)**. 
The CORS configuration, written in JSON, allows clients to access resources in a different domain from applications within the same domain.

Scroll down a bit more, and you will see a section where you can edit CORS settings. 


Paste the below JSON into it to enable the upload of files from the front end, or you will receive a CORS error while uploading files.

![Editing CORS Policy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ao4xc1vpoovglxsk5ghd.png)

```javaScript

[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "PUT",
            "POST",
            "DELETE",
            "GET"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": []
    }
]

```

Uploading files to your AWS S3 bucket is now possible. 

Next, we'll talk about the front end.

Run the command below to Scaffold your react application.

```javaScript

npx create-react-app filestorage
cd filestorage
npm start

```
## Installing AWS SDK for JavaScript

You must install the AWS SDK for JavaScript, allowing your React JS application to communicate with S3.

Run the command below to install AWS SDK

```javaScript
npm install aws-sdk
```

Next is to replace the default code in the App.js file with the code below

```javaScript
import React, { useState } from 'react';
// Uncomment one of the following import options:
import AWS from 'aws-sdk'; // Import entire SDK (optional)
// import AWS from 'aws-sdk/global'; // Import global AWS namespace (recommended)
import S3 from 'aws-sdk/clients/s3'; // Import only the S3 client

import './App.css';

function App() {
  const [file, setFile] = useState(null);
  const [uploading, setUploading] = useState(false)

  const allowedTypes = [
    'image/jpeg',
    'image/png',
    'application/pdf',
    'video/mp4',
    'video/quicktime',
    'audio/mpeg',
    'audio/wav',
    // Add more supported types as needed
  ];

  const handleFileChange = (event) => {
    const selectedFile = event.target.files[0];
    if (allowedTypes.includes(selectedFile.type)) {
      setFile(selectedFile);
    } else {
      alert('Invalid file type. Only images and PDFs are allowed.');
    }
  };

  const uploadFile = async () => {
    setUploading(true)
    const S3_BUCKET = "your_bucket_name"; // Replace with your bucket name
    const REGION = "your_region"; // Replace with your region

    AWS.config.update({
      accessKeyId: "your_accesskeyID",
      secretAccessKey: "your_secretAccessKey",
    });

    const s3 = new S3({
      params: { Bucket: S3_BUCKET },
      region: REGION,
    });

    const params = {
      Bucket: S3_BUCKET,
      Key: file.name,
      Body: file,
    };

    try {
      const upload = await s3.putObject(params).promise();
      console.log(upload);
      setUploading(false)
      alert("File uploaded successfully.");

    } catch (error) {
      console.error(error);
      setUploading(false)
      alert("Error uploading file: " + error.message); // Inform user about the error
    }
  };

  return (
    <>
      <div className="">
        <input type="file" required onChange={handleFileChange} />
        <button onClick={uploadFile}>{uploading ? 'Uploading...' : 'Upload File'}</button>
      </div>
    </>
  );
}

export default App;


```
The React code above creates a simple file uploader app. Users can select a file that is uploaded to an Amazon S3 bucket. 

Here's a brief breakdown:

- **State Management:** It uses React's useState hook to manage the selected file and uploading state.

- **Allowed File Types:** Defines an array of allowed file types.

- **File Change Handler:** When a file is selected, it checks if the file type is allowed and updates the state with the selected file.

- **Upload Function:** Constructs S3 parameters and uploads the file to the specified S3 bucket. It handles success and error cases, providing feedback to the user.

- **User Interface:** Provides a file input field and a button for uploading—the button text changes based on the uploading state.

- **AWS SDK:** Imports necessary modules from the AWS SDK to interact with S3 and configures it with credentials and region.

The code offers a basic file uploading functionality to S3 from a React app.

# Conclusion

You've successfully uploaded a file to your S3 bucket with these steps! You can consult the documentation for tailored options that suit your specific requirements.