Uploading to S3 using NestJs

Visakh Vijayan - May 12 '21 - - Dev Community

Gone are those days when we used to store images on our servers. Nowadays we have dedicated image servers for that purpose like AWS S3, Cloudinary, and more. The reason it's better to store on these specialized servers is because of the inbuilt image manipulation tools they come with. They can resize, add watermarks and do much more.

Here is a simple way to upload files to AWS S3 using NestJs.

  1. You will have to create a bucket on S3 for this first. A bucket is like a folder for your stuff.
  2. You will need the aws-sdk package from npm for this.
  3. Get the ACCESS_KEY and KEY_SECRET from aws.
  4. Create a service file so that it can be injected everywhere on demand.
  5. Keep all your confidential keys in your .env file.
import { Injectable, Req, Res } from '@nestjs/common';
import * as AWS from "aws-sdk";

@Injectable()
export class S3Service
{
    AWS_S3_BUCKET = process.env.AWS_S3_BUCKET;
    s3 = new AWS.S3
    ({
        accessKeyId: process.env.AWS_S3_ACCESS_KEY,
        secretAccessKey: process.env.AWS_S3_KEY_SECRET,
    });

    async uploadFile(file)
    {
        const { originalname } = file;

        await this.s3_upload(file.buffer, this.AWS_S3_BUCKET, originalname, file.mimetype);
    }

    async s3_upload(file, bucket, name, mimetype)
    {
        const params = 
        {
            Bucket: bucket,
            Key: String(name),
            Body: file,
            ACL: "public-read",
            ContentType: mimetype,
            ContentDisposition:"inline",
            CreateBucketConfiguration: 
            {
                LocationConstraint: "ap-south-1"
            }
        };

        console.log(params);

        try
        {
            let s3Response = await this.s3.upload(params).promise();

            console.log(s3Response);
        }
        catch (e)
        {
            console.log(e);
        }
    }
}

Enter fullscreen mode Exit fullscreen mode

A couple of points to look out for here are - ACL which makes your file readable to the public. Else AWS shows "Access Denied". ContentDisposition: "inline" and ContentType - so that your file is viewed by the browser and not downloaded.

And the response structure looks like this

{
  ETag: '"<unique-key>"',
  Location: 'https://<bucket>.s3.amazonaws.com/<filename>',
  key: '<filename>',
  Key: '<filename>',
  Bucket: '<bucket>'
}
Enter fullscreen mode Exit fullscreen mode

The location key is what you want.

Happy programming!!!

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .