Image and Video Upload to Cloudinary using NextJs Server-Side, Multer, and Xata Database
Tags: javascript, cloudinary, xata, nextjs
Published: 2022-11-23 14:08:08

![Uploading a file to the cloud. Image by rawpixel.com on Freepik](https://paper-attachments.dropboxusercontent.com/s_13D9629A17BA205412E87FA69ADEF80CA77BC359F9970BA6A590DF17482B2D39_1667844484191_apply-voucher-code-starting-download.jpg)


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](http://hackmamba-xata-cloudinary-project.vercel.app/) 

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




## Live DEMO

https://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](https://paper-attachments.dropboxusercontent.com/s_13D9629A17BA205412E87FA69ADEF80CA77BC359F9970BA6A590DF17482B2D39_1667844528645_flashcardHLM.drawio.png)


Visit the live URL above to see the application.

----------

## The Backend

**Cloudinary Installation and Configuration**

**1. Install Cloudinary**

Run this command.


    npm install cloudinary


**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](https://cloudinary.com?utm_source=hackmamba&utm_campaign=hackmamba-hackathon&utm_medium=hackmamba-blog) 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](https://paper-attachments.dropboxusercontent.com/s_989AA707FBDB1A6E245B0183CDBE36E7057DC650108E1558D444FCEE5091CDDF_1667441247189_Screen+Shot+2022-11-03+at+3.06.15+AM.png)


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](https://paper-attachments.dropboxusercontent.com/s_13D9629A17BA205412E87FA69ADEF80CA77BC359F9970BA6A590DF17482B2D39_1668196350401_Screen+Shot+2022-11-03+at+3.13.08+AM.png)



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


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

{% embed https://gist.github.com/Theodore-Kelechukwu-Onyejiaku/dc66ae200d4f15ce7ff70f2ea0854ab4 %}

**Xata Installation and Setup**


**1. Create a Xata account.**

Click this [link](https://app.xata.io/?utm_source=hackmamba&utm_campaign=hackmamba-hackathon&utm_medium=hackmamba-blog) 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](https://paper-attachments.dropboxusercontent.com/s_13D9629A17BA205412E87FA69ADEF80CA77BC359F9970BA6A590DF17482B2D39_1667831780673_Screen+Shot+2022-11-07+at+3.35.51+PM.png)


**Cards Table**

![Cards Table](https://paper-attachments.dropboxusercontent.com/s_13D9629A17BA205412E87FA69ADEF80CA77BC359F9970BA6A590DF17482B2D39_1667831850926_Screen+Shot+2022-11-07+at+3.37.12+PM.png)




**3. Install Xata Database**

Watch the video [here](https://xata.io/docs/quickstart/building-a-web-app-with-xata-and-nextjs) and see this installation documentation. Or,


- Install Xata CLI:


```
npm install -g @xata/cli
```

- Next, connect with Xata database:

```
xata auth login
```

 
 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](https://paper-attachments.dropboxusercontent.com/s_13D9629A17BA205412E87FA69ADEF80CA77BC359F9970BA6A590DF17482B2D39_1668194363934_Screen+Shot+2022-11-11+at+8.19.09+PM.png)


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


![Successful Authentication of Xata CLI](https://paper-attachments.dropboxusercontent.com/s_13D9629A17BA205412E87FA69ADEF80CA77BC359F9970BA6A590DF17482B2D39_1668195045165_Screen+Shot+2022-11-11+at+8.30.27+PM.png)


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


- Initialize our project with Xata


```
xata init
```

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:

{% embed https://gist.github.com/Theodore-Kelechukwu-Onyejiaku/1e2e1ad1d04e2f307b1fcb37296706d8 %}

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


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

{% embed https://gist.github.com/Theodore-Kelechukwu-Onyejiaku/bf17de385ba3363ebfff30702f1b74e0 %}

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 **line****s** **115-126**  below.

{% embed https://gist.github.com/Theodore-Kelechukwu-Onyejiaku/0ed6d857c770d88a3688b141a8456f66 %}

**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`.

{% embed https://gist.github.com/Theodore-Kelechukwu-Onyejiaku/8f5ebd1e082bc313499bb71d005a7fed %}

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:

{% embed https://gist.github.com/Theodore-Kelechukwu-Onyejiaku/c3e26f5aead5f6d592b50ac468dc4b93 %}

### Deleting Images and Videos 

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

{% embed https://gist.github.com/Theodore-Kelechukwu-Onyejiaku/4e28cf9818821e4468102a451a9b512a %}

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

## Live Demo
https://hackmamba-xata-cloudinary-project.vercel.app/

## 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](https://hackmamba-xata-cloudinary-project.vercel.app/).