Upload image to AWS S3 (Localstack) using Nest + Typescript.

Boro
Geek Culture
Published in
4 min readJul 26, 2021

At some point in time as a developer, you would very well come across using AWS S3 bucket as storage for uploading files. And that’s what we try to accomplish today. I will take you through the entire flow and let you know the exact setup/configuration I use to start storing any type of files in S3. I’ll be using Nest.js and Typescript for the demonstration. Although you can store anything in an S3 bucket (text files, images, videos, blobs), we will be dealing explicitly with images since we only want to store image files for the demonstration.

On a side note, we will not require any access/secret AWS config keys since we will be using localstack as the development environment. Localstack, if you don’t know already basically helps us avoid the tedious upfront work that you would generally put in configuring the development environment which I’d say can be a lot time-consuming. In case if you do want to have the access/secret keys, you are great to have those. Include them in a .env file and make sure to pull it out in the S3 config provider file.

Also, I am using the localstack docker image that will help me support the AWS cloud services like S3. Go ahead and pull the localstack docker image if you don’t have it already. Once you install that, you will be ready to keep going. If you are looking for a guide that will help you install and configure localstack you can visit their Github.

Quick steps to install localstack

  • Download the Docker Desktop for your system. You can find the downloadable files here.
  • Pull the localstack docker image from Docker Hub. You can find the image here.

S3 Config Provider

We have the S3 config provider that does all the setups that we require to get started. Since we don’t actually require any real access/secret keys we can hardcode the keys like so or if you have the keys be sure to pull it out from the .env file. We now have the S3 object with the required config. We have the methods getS3() and getBucketName() to export the S3 object and the name of the bucket to be used anywhere in the project.

Also, be sure to run the createBucket() method once to create a bucket for you with the bucket name testbucket. You can make use of the last line to create a bucket.

Defining the DTO

Let us define the DTO of the image file object along with the response object that we will receive once we upload the image to the S3.

We are all set with the DTO. Now we can go ahead and define the only route that will handle the HTTP POST request in the controller.

Controller Class

Inside the controller file, we define the route or path prefix /upload that will take care of the action to upload the image file to S3. We are using FileInterceptors to only intercept files with a specific key. The upload method below will delegate the rest of the operation to the service file by calling the upload method inside the service file which performs the required logic to upload the image to S3.

The primary objective of a controller is to handle incoming requests to one of its endpoints and return responses back to the client. Here, we finally return a response success/error object notifying if the image was uploaded or not. Let us now write the logic to actually upload the image to S3 inside the service class.

Service Class

The service class (ImageUploadService) is responsible for uploading the image to S3 and is designed to be used by the UploadImageController. What we have here is a basic service class. It creates an instance of the S3 provider to grab the actual S3 object to perform the upload operation on it.

The essence of a service class or a provider is to organize and share business logic, data, or functions with multiple components within an application.

We finally return a promise with the resolve/reject object based on if the operation was successful. The very next step is to bundle up the controller and the service file under one roof. A module is commonplace to group components, and services, which are related to the application. Let us do it using the module class.

Module Class

The UploadImageModule class creates a module with the controller and provider files that we’ve created earlier. Every module that we create inside a project can be shared. For example, if we had another module importing the UploadImageModule, it would have access to the UploadImageService and its methods.

The very last step is to actually import this module (UploadImageModule) into the root app module. Let us do just that for the final step.

Once we are done importing the UploadImageModule to the root AppModule we are good to test the application. We will be using the Thunder Client VSCode extension to test the endpoint. Before firing up the Thunder client make sure to run the Nest server and localstack using the commands below:

Thunder Client (Testing the `/upload` endpoint)

We can see from the image above we receive a response back with the data object containing the Link (URL) of the image uploaded to S3. The image is now accessible from the URL. There you go we are now finally done with implementing a service that uploads image files to an S3 bucket.

Thanks for sticking around.

References

--

--

Boro
Geek Culture

I write about web design, front-end technologies, development and best practices at large.