DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Cover image for Image and Video Upload to Cloudinary using NextJs Server-Side, Multer, and Xata Database
Theodore Kelechukwu Onyejiaku for Hackmamba

Posted on • Updated on

Image and Video Upload to Cloudinary using NextJs Server-Side, Multer, and Xata Database

Uploading a file to the cloud. Image by rawpixel.com on Freepik

It may not be surprising that one has already uploaded a file today, whether it will disappear after a time or be stored in an online database. Thus, It has become imperative to create applications enabling file uploads. Using NextJs server-side, one can implement this.

This article is in two parts. In the first part, we discuss the frontend, where we will talk about what our project does and the tools needed. Then the second part is about implementing image and video uploads to Cloudinary and how to persist data in Xata Database.

What we are Building

The project is a digital flashcard for memorizing. A flashcard aids in learning what one wants to remember. A physical flashcard has a front and a back; the front usually poses a question, and the reverse usually offers the solution. A digital flashcard allows us to add images and videos to help us better remember an idea, code, nation's flag, etc.

The advantages of a flashcard are listed below.

  • It aids in enhancing visual memory.
  • They promote learning rate and are constantly portable.
  • For acronyms, mathematical formulas, algorithmic codes, etc., flashcards are instructive.
  • It is affordable.

See demo here

GitHub URL

https://github.com/Theodore-Kelechukwu-Onyejiaku/hackmamba-xata-cloudinary-project

Live DEMO

http://hackmamba-xata-cloudinary-project.vercel.app/

The Frontend

The frontend part of our work deals with how we interact with our project as seen in the live URL shared above. Here are the tools used for the frontend.

Frontend Tools

Using the npm i <tool_name> command we can install them.

  • aos : This is used for the animation of cards as we scroll down the application.
  • react-icons : this was used to display icons in our project.
  • react-quill: for the WYSIWYG editor for adding front and back content.
  • react-toastify: this was used for the toast notifications in our app.
  • Tailwind CSS: this is the main CSS of our application. Please note that other custom CSS was used in the project. Visit the Github URL above to see all.

Frontend Logic

Here is the logic of our application.

  • A user registers by utilizing the Credentials or Github providers (email and password). Look at the file at 'pages/auth/signup' in the Github URL.
  • After successful registration, the user is routed to the login page "pages/auth/signin."
  • After successfully logging in, the user can view all of the cards that other users have made.
  • We can choose from options like making a card, seeing our collections and cards, searching for a card based on its name or category, switching between dark and light settings, like a card, and watching a video.
  • The card name, category, image, optional video, and front and back content must all be added before a card can be created.
  • The user can begin flipping cards to practice memorizing, and films and visuals will assist them to develop their memory.
  • A user who is the card's owner can update or delete the card once it has been created.
  • A user can add a freshly made card to their collection by clicking the Plus symbol while they are not the owner of it.
  • There are three options for editing a card. We have the option to only update the card's image, video, or other information.
  • We can search for a card by typing its name or its category into the search box.

Below is a High-Level Model of the frontend logic:

HLM for Digital Flashcard Project

Visit the live URL above to see the application.


The Backend

Cloudinary Installation and Configuration

1. Install Cloudinary

Run this command.

npm install cloudinary
Enter fullscreen mode Exit fullscreen mode

2. Create a Cloudinary Account

We need our Cloudinary cloud name, API key, and API secret to proceed. Head over to the Cloudinary website here to get these three.

Click on the dashboard tab. There, we will find our API key, API secret, and cloud name.

Get the Cloud Name, API Key and API Secret of Our Cloudinary Account

Click on settings, then click on upload. There*,* you can be able to add presets.
Give the name and folder the value β€œflashcard” and click "save".

Create a Preset on Cloudinary

3. Add Cloudinary details to .env.local file

Create a .env.local file and add the following.

// .env.local
CLOUDINARY_API_KEY=<our_key>
CLOUDINARY_API_SECRET=<our_api_secret>
CLOUDINARY_NAME=<our_cloud_name>
Enter fullscreen mode Exit fullscreen mode

4. Create Cloudinary Configuration file

Create a folder in the root of our project called utils. Inside it, create a file cloudinary.js and add the following code.

Xata Installation and Setup

1. Create a Xata account.

Click this link to create a Xata account.

2.Create Database and Tables

If we are new to Xata on creating tables, please read and visit these links https://xata.io/docs/intro/getting-started and https://xata.io/docs/quickstart/index. Now create a database called β€œtest” or β€œflashcard”. After that, create the following tables:

Users Table

Users Table

Cards Table

Cards Table

3. Install Xata Database

Watch the video here and see this installation documentation. Or,

  • Install Xata CLI:
npm install -g @xata/cli
Enter fullscreen mode Exit fullscreen mode
  • Next, connect with Xata database:
xata auth login
Enter fullscreen mode Exit fullscreen mode

We choose β€œ Create a new API key in browser” when our terminal prompts us. This opens a browser. We enter the name of our API key.

Generating an API key for our Xata CLI

If successful, we will see this on the browser page.

Successful Authentication of Xata CLI

A message β€œAll set! you can now start using xata” will be displayed on our terminal.

  • Initialize our project with Xata
xata init
Enter fullscreen mode Exit fullscreen mode

We choose the following during the terminal prompts;

  • Select existing database β€œtest” or β€œflashcard”.
  • Select β€œGenerate Javascript code with ES modules” for β€œDo you want to use code generation in our project”.
  • Type in β€œutils/xata” for β€œChoose the output file for the code generator”.
  • Select β€œno” for β€œDo you want to generate the TypeScript declarations?”.
  • For β€œChoose a default development branch (fallback branch)” select β€œmain”.
  • Lastly, for β€œDo you want to create a .gitignore file and ignore the .env file?, select β€œyes”.

Once done, we should see the message β€œYou are all set!”

Make sure to select utils/xata as where our Xata Codegen file will reside. If successful, our xata.js file should look like this:

Uploading Images and Video

Since this will be done on the NextJs server side, the following packages are to be installed.

npm i bcrypt datauri multer next-auth next-connect
Enter fullscreen mode Exit fullscreen mode
  • bcrypt: this will help in authentication, hashing of passwords, and verification.
  • datauri : will help us convert parsed files(image and video) to base 64 encodings.
  • multer : will help us parse the request body.
  • next-auth : this will add authentication.
  • next-connect: this will help us add Multer as a middleware to a route handler.

Create a create-card.js file

We have to create a card to upload an image and a video. So create a file called create-card.js inside the api folder of the pages folder.

This will handle any POST request to /api/create-card.. So, the frontend will send form data, including the image and video we want to upload.

  • Line 1: we import the package next-connnect .
  • Line 9: we create a new Xata instance.
  • Line 20: we apply the Multer middleware. The Multer middleware ensures that it parses any files using the any() method. And we store the image and video for each card inside the variables image and video in lines 30 and 31.
  • Line 33: we create the datauri/parser instance to convert the parsed files to a base 64 encodings file. This way, we can upload the image and video generated in lines 40 and 47 to cloudinary.
  • Line 36-40: here, we convert the parsed image file to a base 64 encoding for upload to Cloudinary. This is done using the uploader.upload() method of the Cloudinary SDK. Notice we passed in the upload presets, flashcards, and an option { resource_type: 'image' } telling Cloudinary that this is an image we want to upload. This method returns a response, including the URL of the new Image created, which is stored in the database as image.
  • Line 43-47: Same as Line 36-40. The only difference is this time, we tell Cloudinary that it is a video { resource_type: 'video' }.
  • Line 60-73: we create a new card by invoking the create() function of Xata and passing the values from the frontend.

See what will be sent from the frontend in lines 115-126 below.

Updating an Existing Image
Updating an existing image in Cloudinary also means updating our card. Create a new API route handler called update-card-image.js.

There is not much difference from create-card.js.

  • Line 17: we told Multer that it should parse a single file named image. This is the name of the form data image from the frontend.
  • Line 37: we delete the existing Cloudinary image of a card by invoking the Cloudinary destroy() method. This method only requires the id of the image to delete.
  • Line 43: we update the card with the new image URL, id, and signature.

Updating an Existing Video
This is the same as the code above. We will create a new file called update-card-video . The only difference is that this time we tell Multer to parse a file named β€œvideo” in line 17. See the code below:

Deleting Images and Videos

In deleting a card, we thereby delete the image and video.

  • Line 21 and 26: we call the Cloudinary destroy() methods and passed the image id and video id of the card we want to delete.
  • Line 30: we invoke the delete() method of Xata by passing the id of the card we want to delete.

Conclusion

In this article, we looked at uploading images and videos to Cloudinary using NextJs Server Side and persisting data in the database using Xata. The frontend and full code have been provided in the GitHub URL section of this article. Once again, visit here for the live application.

Top comments (13)

Collapse
 
ajibilaridwan profile image
Adeniran Ridwan Ajibola

Very educative!

Collapse
 
javascriptar profile image
Theodore Kelechukwu Onyejiaku

Thanks. I am glad you find it educative!

Collapse
 
chyke007 profile image
Nwachukwu Chibuike

Really great piece

Collapse
 
zeldalaw007 profile image
ZELDA

Amazing Write Up!

Collapse
 
sammychinedu2ky profile image
sammychinedu2ky

Nice one man !!!

Collapse
 
javascriptar profile image
Theodore Kelechukwu Onyejiaku

Thanks Sammy 😊

Collapse
 
vicradon profile image
Osinachi Chukwujama

Nice one

Collapse
 
javascriptar profile image
Theodore Kelechukwu Onyejiaku

Thanks Osi πŸ˜ŠπŸ™Œ

Collapse
 
chiderandukwe profile image
Chidera

I feel I could easily use Xata right away after reading through this. I appreciate your insightful article,

Collapse
 
elinoc4 profile image
Elijah Chinweuba Azubuike

Very insightful

Collapse
 
munah profile image
Mu-nah

helpfully detailed article.....

Collapse
 
alvan profile image
Achonwa Alvan

Great one champ.

Collapse
 
shittu_olumide_ profile image
Shittu Olumide

I love this, thank you so much!

11 Tips That Make You a Better Typescript Programmer

1 Think in {Set}

Type is an everyday concept to programmers, but it’s surprisingly difficult to define it succinctly. I find it helpful to use Set as a conceptual model instead.

#2 Understand declared type and narrowed type

One extremely powerful typescript feature is automatic type narrowing based on control flow. This means a variable has two types associated with it at any specific point of code location: a declaration type and a narrowed type.

#3 Use discriminated union instead of optional fields

...

Read the whole post now!