In previous posts, I explained how to upload images, and render them in the browser using a Drag & Drop component written in Angular and TypeScript. That project has considered a secure cloud storage system for the uploaded files, provided by Cloudinary.
However, that solution didn’t consider Authenticated Uploads, which means that every API call was unsigned.
In this MediaJam we’ll add an additional layer (server-side code) using NestJS to provide signed uploads to the cloud.
You’ll need to have installed the following tools in your local environment:
- The latest LTS version of Node.js version available is recommended.
- Either NPM or Yarn as a package manager
- The Nest CLI tool(Command-Line interface for NestJS)
- The Angular CLI tool (Command-line interface for Angular)
Also, just make sure you have your Cloudinary account ready to use (you must verify your email if it’s your first time with the platform).
Let’s create a brand-new project using the Nest CLI tool following this syntax.
nest new <project-name>Code language: HTML, XML (xml)
In this case, we’ll use
image-server as the name, and the project will be implemented as the backend for the existing frontend application.
The previous command should create a project ready-to-go, and it will install all the initial dependencies required by the project.
Now, open the
image-server project in your favorite code editor, and pay attention to the autogenerated files and directories.
|- image-server/ |- src/ |- main.ts |- app.module.ts |- app.controller.ts |- app.service.ts
By default, you can run the initial project (just to make sure it is working fine) using
npm run start:dev. This command will run the project in a watch mode and it means the project will be rebuilt after every change you apply in the source code. Useful, right?
The Cloudinary platform provides a variety of options for customizing how the files can be uploaded from your application. For example, you can upload the files using the REST API or using a client library for your programming language.
In this case, we’ll proceed to install the Node.js SDK using the following command.
npm install cloudinary
The Cloudinary’s Node.js SDK provides a simple way for image, and video uploading as we are going to see later.
In the Angular world, we usually create a module to group components, directives, services, pipes, etc. In the same way, we can create a module to group content in a NestJS project.
The NestJS CLI tool provides also a way to generate different files for us. Let’s proceed to create a module, a service, and a provider:
In order to use the Node.js SDK, you must configure the
api_key, and the
api_secret. These values are account-specific and can be found on the Dashboard page of your account console.
In other words, this is a useful way to configure the SDK globally instead of configuring each call.
Let’s open the
cloudinary.provider.ts file, and add the following code.
- The first line imports the
v2of the available API and assigns an alias to it as
- Next, a Custom Provider is defined using the
useFactorysyntax for creating a provider dynamically.
- The factory function takes the
cloudinaryAPI and performs the configuration using environment variables, which is a suggested method for storing the keys.
Remember to never expose your API keys in the source code!
One of the good things about the Node.js SDK is the addition of the response models:
Let’s create a union type with both of them in a new file
We’ll use the union type for the service implementation in the next section.
As in the Angular world, we can create a Service to have an additional layer to handle the upload operation. Also, the service can be reused from different controllers if that’s needed.
Let’s update the
cloudinary.service.ts file, and create the
uploadFile method as follows.
So what’s happening in the above code snippet?
uploadFilemethod is ready to receive a File using the Node.js middleware for handling
multipart/form-data, which is used for uploading files. This method will return a
cloudinary.uploader.upload_stream()writes down the uploader as a stream. There are different options for uploading to the cloud from Node.js or even the browser.
There’s an interesting note to take here: The
Express.Multer.File is an object containing the file metadata, and it’s possible to access a
Buffer containing the file itself using
However, before uploading this “File” to the cloud, it’s necessary to convert the Buffer into a Readable Stream for the SDK. There are several options to perform this operation, and this solution adds the
streamifier package from NPM.
Install the package as part of the project:
npm install streamifier
And then you’ll be ready to convert any
string into a
Readable Stream through the
Read more about
cloudinary.upload_stream method here.
Let’s update the
cloudinary.module.ts file to ensure the right configuration of the Node.js SDK, and the Service:
As you can see, it’s required to export both
CloudinaryService from this module.
Let’s work with the
app.controller.ts file to configure an appropriate route before writing the
@Controller('image') decorator will define the base path as
/image, and along with the
@Post('upload') decorator, will define the
POST /image/upload endpoint.
On other hand, an instance of the
CloudinaryService class is injected into the controller as a private attribute:
NestJS has implemented File Upload capabilities to make it easier for us. It provides a built-in module based on the multer middleware package for Express. And, for better type safety, you must install the typings package:
npm install --save-dev @types/multerCode language: CSS (css)
This middleware is enabled to handle
multipart/form-data, which is primarily used for uploading files.
It’s time to implement the
The previous method is meant to upload a single file. Then, a
FileInterceptor is needed to “catch” the file, and it can be extracted from the request using the
Finally, it performs a call to the
CloudinaryService implemented above to delegate the upload behavior through the SDK. The service will return a
Promise with either a
Of course, it’s possible to process multiple files in a single method. This can be done using the
@UploadedFiles() decorator instead:
You can see that we use the
FilesInterceptor', and that it can be configured to support a maximum of 5` files to be uploaded at the same time.
As the documentation site says:
Cross-origin resource sharing (CORS) is a mechanism that allows resources to be requested from another domain.
You’ll find the following error in the browser’s console if you don’t have it enabled:
NestJS makes use of the Express
cors package and it can be customized for you. To enable CORS, just add a call to
enableCors() method as follows in the
Find the source code available in GitHub both for the Backend (using NestJS) and the Frontend (using Angular).
If you prefer, you can play around with the project in CodeSandbox – Uploading Images to Cloudinary with Angular too, to see the image uploading in action: