# How to upload files to S3 from Node.js

> Learn how to upload files to AWS S3 from Node.js: create a bucket and an IAM user, store the keys in .env, then send the file with the aws-sdk s3.upload().

Author: Flavio Copes | Published: 2021-06-22 | Canonical: https://flaviocopes.com/node-upload-files-s3/

I had a simple use case. 

I was building a job board and it was time to build the form to submit a new job offer.

The recruiter can enter the company details, the job details, and the company logo image.

The data is stored in the database, and at first I tried to store the logo in the database, but after a while I realized that while technically ok, I had some issues with storing the binary data and it was taking too long for the task. So I said, "ok let's just upload it to S3".

S3 is one of the wonderful services provided by AWS. Since I already use AWS for other things, adding a S3 bucket is easy.

So I went to create an S3 bucket.

I already had an AWS account. If you don't, start here: <https://aws.amazon.com>.

Once you have an account set up, create a IAM user in AWS. Login to AWS, click your name on top and then "My Security Credentials"

![AWS console dropdown menu showing My Security Credentials option](https://flaviocopes.com/images/node-upload-files-s3/Screen_Shot_2021-06-08_at_14.42.05-redacted_dot_app.png)

On the sidebar click "Users", and "Add user". Enable "Programmatic access".

![AWS Add user form with Programmatic access checkbox selected](https://flaviocopes.com/images/node-upload-files-s3/Screen_Shot_2021-06-08_at_14.43.24.png)

Move to the next screen via the buttons you find in the bottom of the page ("Next: Permissions").

Click the "Attach existing policies directly":

![AWS IAM permissions screen with Attach existing policies directly option highlighted](https://flaviocopes.com/images/node-upload-files-s3/Screen_Shot_2021-06-08_at_14.44.24.png)

Type "S3" in the filter to show the S3 policies

![AWS IAM policies filtered by S3 showing Amazon S3 related policies](https://flaviocopes.com/images/node-upload-files-s3/Screen_Shot_2021-06-08_at_14.44.41.png)

Select the `AmazonS3FullAccess` permission:

![AWS IAM policies list with AmazonS3FullAccess policy selected](https://flaviocopes.com/images/node-upload-files-s3/Screen_Shot_2021-06-08_at_14.44.57.png)

Once the user is created, you'll have a pair of access key ID and secret access key. Copy those to your `.env` file in the project you have, or store them somewhere so you can use them later.

Next, go in S3 and create a bucket. From the S3 homepage <https://s3.console.aws.amazon.com> click the "Create bucket" button.

Set a name, choose an AWS region, disable "Block all public access" (we'll get to permissions in another post) and click the Create bucket button at the bottom of the page.

![AWS S3 Create bucket form with bucket name and region settings](https://flaviocopes.com/images/node-upload-files-s3/Screen_Shot_2021-06-08_at_14.47.39.png)

Done! Now it's time to dive into [Node.js](https://flaviocopes.com/nodejs/). I use this code in [Next.js](https://flaviocopes.com/nextjs/), server side, in an API call.

First install the [`aws-sdk`](https://www.npmjs.com/package/aws-sdk) package with `npm install aws-sdk`.

As mentioned, store your AWS access codes in `.env`:

```
AWS_ACCESS_KEY_ID=<the access key>
AWS_SECRET_ACCESS_KEY=<the secret>
AWS_BUCKET_NAME=<the bucket name>
```

Add

```js
import AWS from 'aws-sdk'
```

on top.

Then initialize the `s3` object with:

```js
const s3 = new AWS.S3({
  accessKeyId: process.env.AWS_ACCESS_KEY_ID,
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
})
```

Now when you want to upload a file, load it from the storage

```js
const filename = 'the-file-name'
const fileContent = fs.readFileSync(fileName)

const params = {
  Bucket: process.env.AWS_BUCKET_NAME,
  Key: `${filename}.jpg`,
  Body: fileContent
}

s3.upload(params, (err, data) => {
  if (err) {
    reject(err)
  }
  resolve(data.Location)
})
```
