Get On Board With the Media Express
Tags: express, multer, cloudinary
Published: 2019-03-12 20:08:20

---
title: Get On Board With the Media Express
published: true
description: Image Uploads, Retrievals $ Uploads To And From Cloudinary
tags: Express, Multer, Cloudinary
---
 ![Alt Image Uploads $ Retrievals](https://thepracticaldev.s3.amazonaws.com/i/k18xm2azna0k21llj24g.png)

In today’s online world, the delivery speed of your eCommerce web and mobile apps is a paramount factor in user experience. If your customers become frustrated by a lengthy load time for your website, they might stop visiting it, putting your online presence at risk. The fact is, people judge your brand by how well they can interact with your web and mobile apps before contacting you in person.

For web developers, managing digital assets, such as videos, photos, music, and other multimedia, is a must-do. Poor handling of that task might lead to slow performance of your apps, causing a dismal user experience.

No worries,[Cloudinary](https://cloudinary.com/) is here to the rescue.

Cloudinary is a cloud-based platform for managing images and videos, enabling businesses and developers to focus on their specialties. In fact, management of digital assets is Cloudinary’s core business.

This article steps you through the process of developing a simple, web-based app that creates, reads, and deletes media from the Cloudinary servers.

## Installing NPM
To start, download the most stable release of the Node.js binaries from [`https://nodejs.org`](`https://nodejs.org`).Afterwards, install them on your machine by following the procedure on the page that pertains to your platform.

To confirm the installation, type these two commands:

`node -v`
`npm -v`

The output displays the version numbers of your Node.js and the Node Package Manager (NPM), a tool for installing, uninstalling, and maintaining package modules for apps.

## Initializing a New App

A basic Node app contains a `.js` file and a `package.json` file, which does the following :

* Specifies the packages on which your project depends,
* Lists the versions of a package that your project can use according to the 
  [`semantic versioning`](`https://docs.npmjs.com/about-semantic-versioning`)rules.
* Makes your build reproducible, hence easier to share with other developers.

To generate a `package.json` file for your app, navigate to your project folder in a terminal or, for Windows users, in Git Bash, and type the following command:

`npm init -y`

Running the above command without the flag `-y` generates questions that prompt for answers from you, which would clearly describe the app and its dependencies.

## Installing the Required Dependencies
Run this command to install the required dependencies:
`npm install express body-parser multer express-handlebars moment dotenv cloudinary --save`

Below are the dependencies:
* **`express`**: A web-app framework for Node.js.
* **`body-parser`**: A middleware that handles post requests in `express`.
* **`multer`**: The Node.js middleware for handling multipart `FormData`.
* **`express-handlebars`**: A Handlebars view-engine for `express`.
* **`moment`**: A lightweight JavaScript date-library for parsing, validating, manipulating, and formatting dates.

* **`dotenv`**: A module that loads environment variables from a `.env` file into the `process.env` property.
* **`cloudinary`**: A Node.js wrapper that enables you to communicate with the Cloudinary servers.
Once the dependency packages are in place, edit the `package.json` file to read like this:

![Alt package.json](https://thepracticaldev.s3.amazonaws.com/i/j8lfpp11wvvyh7b3dl26.png)

As specified in the file, the entry point to your app is the `server.js` file. That is where you will document most of the logic on which the app depends.

## Starting the Server
Next, start the server by adding the following code to the `server.js` file:

`const express = require("express");
const app = express();
app.get("/", (req, res) => res.send("Hello Cloudy"));
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
 console.log(`Server running on ${PORT}`);
});`

Aftwards, start your app by running this command:
`node server.js`

Now go to `localhost:5000` on your browser to verify that the string `Hello Cloudy` is displayed.

## Building the Project Structure
`express-handlebars` is your default templating engine on the front end. To make use of it, do the following:

1. Register the templating engine’s packages by adding the following code to your `server.js` file:

`const exphbs = require('express-handlebars');
app.engine('handlebars', exphbs({defaultLayout: 'main'}));
app.set('view engine', 'handlebars');`

2.Enclose all the front-end files in a folder called `views`.

3. In the `views` folder, create another folder and name it `layouts`, in which the `main.handlebars` file, which contains your app’s front-end structure, resides.

Your app’s project structure now looks like this:
![Alt file_structure](https://thepracticaldev.s3.amazonaws.com/i/8pdm8kkg6bht1fqx6uw0.png)

## Adding Content to the `main.js` and `index.handlebars` Files 
Add the following code to the `main.js` file:

  {% gist https://gist.github.com/musebe/98500650c35d94ffeca7758723837bf4 %}

With the Moustache symbol `{{body}}`, you can seamlessly invoke other pages into the main body.

Next, go to the root of the `views` folder, create an `index.handlebars` file, and then add a media-upload form with the following code to the file:

 {% gist https://gist.github.com/musebe/d88ac548d23002e29c14344da487d1eb %}

Afterwards, run the app on `localhost:5000` on the browser and verify that the form below is displayed:

![Alt frontend](https://thepracticaldev.s3.amazonaws.com/i/we5qdu9xcq0z4thzsq8d.png)

## Configuring Multer

Recall that you installed Multer earlier. That’s a Node.js middleware for uploading or handling multipart `FormData`.

To configure Multer:
1. In the root of your app, create a folder called `handlers` for storing the configurations for Multer and other packages.
2. In the `handlers` folder, create a file called `multer.js` with this configuration code:

`const multer = require("multer");module.exports = multer({
 storage: multer.diskStorage({}),
 fileFilter: (req, file, cb) => {
   if (!file.mimetype.match(/jpe|jpeg|png|gif$i/)) {
     cb(new Error("File is not supported"), false);
     return;
   }cb(null, true);
 }
});`

Next, export `multer.js` to the main `server.js` file by adding this codeline to `server.js`:

`const upload = require("./handlers/multer");`

Then edit the upload route to read like this:

`app.post("/uploads", upload.single("image"), (req, res) => {res.send(req.file);});`

The above steps ensure that when you upload a media file, you can capture the content of the request on the `/uploads` route, as shown here:

![Alt frontend](https://thepracticaldev.s3.amazonaws.com/i/9uitoap73hq0xtb731vr.gif)

## Uploading Media to Cloudinary

The project is now ready for file uploads to Cloudinary. Perform the steps below.

### Initializing the Cloudinary SDK
First, initialize the Cloudinary SDK into the project by adding this codeline to the main `server.js` file:

`const cloudinary = require("cloudinary");`
### Storing and Securing Cloudinary API Keys
To use Cloudinary, you must store its API key, cloud name, and cloud secret in your app. Those keys identify the app or user who’s accessing the Cloudinary servers.
Secure the keys with the `dotenv` package. Even though you can store and use keys without packages, the packages are of great help in managing the keys.
 
To prepare `dotenv` for use:

1. Add these two lines to your `server.js` file:

`require("dotenv").config();
require("./handlers/cloudinary");`

The second codeline above calls for a `cloudinary.js` file in the `handlers` folder.
2.Create a `cloudinary.js` file  in the `handlers` folder with the following content:

`const cloudinary = require("cloudinary");
cloudinary.config({
 cloud_name: process.env.CLOUD_NAME,
 api_key: process.env.API_ID,
 api_secret: process.env.API_SECRET
});`

With this file, the app can locate your server’s access keys that are stored in the `.env` file.

3.Go to the root of the app and create the `.env` file.

If your `.env` file contains confidential values, such as keys, secrets, and passwords, place it in the `.gitignore` folder to prevent it from being committed it to the GitHub repository.

Afterwards, declare your credentials in the `.env` file by adding the following code to it:

`CLOUD_NAME= your_cloud_name
API_ID= id
API_SECRET= secret`

To get the values for those three credentials, first [register](https://cloudinary.com/users/register/free) for a Cloudinary account. Once you are logged in, you’ll see the credential values on your Dashboard. Here’s an example:

![Alt dashboard](https://thepracticaldev.s3.amazonaws.com/i/jgwz57ui5mlmlfdj9jud.png)

### Configuring the `/Uploads` Route

For details on how to perform create, read, update, and delete (CRUD) operations to and from the Cloudinary servers, see the related documentation.

To enable file uploads, configure the `post “/uploads”` route, like this:

`app.post("/uploads", upload.single("image"), async (req, res) => {
const result = await cloudinary.v2.uploader.upload(req.file.path);
res.send(result);

});`

With that configuration, Cloudinary would store the media files that you submit and return to you an object that spells out the properties of those files. See the example below.

![Alt upload](https://thepracticaldev.s3.amazonaws.com/i/tke6fw9w6edgcr4rogj5.gif)
### Setting Up the Cloudinary Upload Widget

In case you worry that uploading media to the Cloudinary servers might take up an inordinate amount of time, worry no more. Cloudinary’s -upload widget renders file uploads a fast process.  For details of the widget, see the related documentation.

Follow these steps to set up the upload widget: 

1. Add a button to your form with the value of the ID (`id`) specified as 
 `upload_widget_opener`, like this:

  `<input value="Upload with Cloudinary Widget" id="upload_widget_opener" 
   class="btn btn-primary btn-block">`

2. Add this script to the `main.handlebars` file to load the widget:

  `<script src="//widget.cloudinary.com/global/all.js" type="text/javascript"> 
   </script>`

3. Set up a handler to listen to a click event of the button element on the web page and then call the widget's `open` method to display the initialized widget. Below is the sample code.

  {%gist https://gist.github.com/musebe/1a3843362be20f59beb91068a4f1d5e9 %}

Finally, change your upload presets from signed to unsigned. To do so, choose Settings > Upload Tab > Upload Presets and make the change in the dialog box that is displayed.

You can now upload media with Cloudinary’s upload widget.

![Alt Image Uploads $ Retrievals](https://thepracticaldev.s3.amazonaws.com/i/hsdxhkbcjx8qe2nyshwn.gif)

## Retrieving Stored Media From Cloudinary in JSON Format
In the `server.js` file, define a `GET “/api/files”` endpoint to call all the files you have stored in Cloudinary. Add the following code:

`app.get("/api/files", async (req, res) => {
const images = await cloudinary.v2.api.resources({
type: "upload",
prefix: "image"
});
return res.json(images);
});`

Afterwards, go to localhost:5000/api/ files on your browser for a display of all your stored files in Cloudinary.


![Alt Api](https://thepracticaldev.s3.amazonaws.com/i/n4jozknlhgyhiit677vh.png)

## Displaying Your Stored Files on the Front End
To display your stored files on the front end, send a GET request to the Cloudinary storage, which will then return an object with all the stored data for conversion into a format that suits the app. For this app, target the `secure_url` and `created_at` fields. 

Create another endpoint in your `server.js` file with the following format:

`app.get("/files", async (req, res) => {
 const images = await cloudinary.v2.api.resources({
   type: "upload",
   prefix: "image"
 });
 // Check if files
 if (!images || images.length === 0) {
   return res.status(404).json({
     err: "No files exist"
   });
 }
// Files exist
 res.render("files", {
   images: images
 });
});`

You can now render all the media on the `/files` route on the browser. However, for that to happen, you must first create the endpoint in the `views` folder and add logic to it to loop and format the responses you receive.

In the `views` folder, create a `files.handlebars` file with the following code:

{%gist https://gist.github.com/musebe/96c19cf35b4256da5dfd4396094853b7 %}

Recall that you’re targeting the `url` and `created_at` endpoints from the server. The code above displays all your media by means of bootstrap cards after looping through the media with the Handlebars’ looping technique.


You’ll now see the following response when you access the route:

![Alt Api](https://thepracticaldev.s3.amazonaws.com/i/pqhw3uh8kv97ai9y4n73.png)

## Deleting Files
You can easily delete a media file  by passing its ID (`id`) in a request, as shown in this example:

`app.delete("/files", (req, res) => {
let id = req.body.id;
cloudinary.v2.api.delete_resources([id], function(error, result) {console.log(result);});
});`

By setting cloudinary.v2.api.delete_resource(), you can capture the ID of the selected media file and delete that file from Cloudinary.

Earlier, on the bootstrap card, you added a button to initiate the delete operation when clicked. Complete that setup by adding the following script under the bootstrap card on the `files.handlebars` route:

`<script>
deleteImage = () => {
const imageClickedID = event.target.id
fetch(`/files`, {
method: 'DELETE',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ id: imageClickedID })
})
.then(location.reload())
.catch(err => console.log(err))
}
</script>`

There! Now you can delete the selected file from Cloudinary by clicking the Delete button.
## Formatting the Date With Moment.Js

The only remaining task is to set up the date and time in a readable format. Do that with a package called `moment`, a lightweight JavaScript date-library for parsing, validating, manipulating, and formatting dates.


You’ve already pulled the package to the project. Now do the following:
Initialize `moment` into the project with this codeline:

`const moment = require("moment");`

Call the `moment` variable for the date-format values by navigating to the line in which you declared your default layout and adding a helper` function:

`helpers: {
renderDateFormat: function(time) {
return moment(time).format("MMMM Do YYYY");}
}`

Open the `files.handlebar` file and add `renderDateFormat` within  the Handlebars` `created_at` helper. Your helper then reads like this:

`{{renderDateFormat created_at}}`

Your app is now all set,  resembling the one hosted on Heroku.

## Checking Out the References
Managing digital media with Express, Multer, and Cloudinary is a painless, seamless, and simple process. In particular, Cloudinary’s robust features greatly accelerate software development that involves digital media. The [Cloudinary documentation](https://cloudinary.com/documentation) contains all the details.
Additionally, feel free to clone and modify the [source code on GitHub](https://github.com/musebe/Cloudy_Crud). Have fun!