DEV Community

eugene musebe
eugene musebe

Posted on • Updated on

Get On Board With the Media Express

Alt Image Uploads $ Retrievals

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 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.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 versioningrules.
  • 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

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.

  1. 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

Adding Content to the main.js and index.handlebars Files

Add the following code to the main.js file:

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:

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

Alt frontend

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

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 for a Cloudinary account. Once you are logged in, you’ll see the credential values on your Dashboard. Here’s an example:

Alt dashboard

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

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">

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

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

  1. 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.

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

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

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:

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

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 contains all the details.
Additionally, feel free to clone and modify the source code on GitHub. Have fun!

Top comments (1)

Collapse
 
elouisramsey profile image
elouisramsey

Hi, how do you upload multiple images with multer and save to cloudinary?