In my last post, I discussed about my plan for integrating cloud storage into an open-source project.
If you haven't read that yet, please take a moment to go through it first before continuing.
In this post, I'll share my progress in executing that plan and any realizations that emerged along the way.
Table of Contents
1. Researching Cloudinary ☁️
1.1. Exploring the SDK 🧰
2. Observing Existing Code 🧐
2.2. UI 💻
2.3. Server Code 🖥️
2.4. Back to UI code
3. Changes Needed
4. Conclusion 🎇
Researching Cloudinary ☁️
As per my plan, the first thing I had to do was research a bit more about Cloudinary and how such cloud services can be consumed by the applications.
Exploring the SDK 🧰
I started out by looking at the getting started page in the official documentation, where it was shown how to install Cloudinary SDK (Software Development Kit), and configure it for various programming languages/frameworks.
For me, since I had to set up in a Node project, I installed it using npm.
npm install cloudinary
And to test if I am able to configure the SDK, I pasted the following boilerplate right before the server starts listening.
// Configure Cloudinary with your credentials
cloudinary.v2.config({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET,
});
As you can see, I also had to setup my credentials as environment variables, so the maintainer could easily swap them with his own account as I won't own the data.
# Cloudinary Secrets
CLOUDINARY_CLOUD_NAME=get-your-own
CLOUDINARY_API_KEY=get-your-own
CLOUDINARY_API_SECRET=get-your-own
Once you sign up for an account, the above credentials can be found on the dashboard page.
But I still had no idea if it worked, and the only way to know was trying to upload a test image to my media library.
As I scrolled a bit in the documentation, they gave me a demo for exactly that.
Referencing the documentation, I tried to upload a sample asset right after the code to configure cloudinary like so.
// Configure Cloudinary with your credentials
cloudinary.v2.config({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET,
});
// Upload Your First Asset
cloudinary.v2.uploader.upload(
"https://upload.wikimedia.org/wikipedia/commons/a/ae/Olympic_flag.jpg",
{ public_id: "olympic_flag" },
function(error, result) {console.log(result); }
);
Now as soon as I started the server,
npm start
I saw the following logs printed in my console.
and in the media library,
Which means my upload was a success, yayy 🎉
This might not seem like something worth celebrating, but ever since I started working on this, I had a doubt at the back of my head if I would be able to make it happen.
This little success relieved a lot of stress from my ❤️, and gave me confidence to keep going.
Observing Existing Code 🧐
Now that I knew that I could upload the images as expected, it was time to look at the existing logic that had to be modified to use Cloudinary.
UI 💻
I started by looking at the UI code, that was sending the images to the server using forms.
I could only recall 2 places where images were being uploaded, user registration and posts.
Starting with user registration felt like a good idea.
I found the register
function and noticed the pattern the owner was using to handle uploads.
The picture
property was a File object, that was captured from the file upload input control.
What I noticed was that apart from sending the normal form data in the request, the owner was also sending an additional property called picturePath
which was basically the name
of the image file being uploaded.
Server Code 🖥️
Now that I knew what was being sent, I had to see how it was being received and handled on the server.
I opened index.js
, the entry point of the server code, and found that any image uploads were being stored in the server's disk storage using a very popular library named multer.
From the official documentation,
Multer is a node.js middleware for handling multipart/form-data, which is primarily used for uploading files.
The files were being saved using their original name as defined in the upload
middleware configuration, which explains why another property picturePath
was being stored with the user
data - to be able to request it back using the same name.
Back to UI code
The last thing I had to see was how the saved image data was being requested back in UI.
import { Box } from "@mui/material";
const UserImage = ({ image, size = "60px" }) => {
return (
<Box width={size} height={size}>
<img
style={{ objectFit: "cover", borderRadius: "50%" }}
width={size}
height={size}
alt="user"
src={`https://chatroomapi-v1.onrender.com/assets/${image}`}
/>
</Box>
);
};
export default UserImage;
As expected, it was being requested from the local storage of server using the picturePath
that was saved in user data.
Changes Needed
It took me a while to understand existing code, but now I it was time to decide what changes had to be made.
This is what I have in mind.
1. I'll have to come up with a way to store the uploaded images temporarily in memory, before finally uploading to cloudinary.
2. Instead of saving the file name in picturePath
property, I should be storing the uri
of the file uploaded to cloudinary.
3. When requesting images back in UI, I need to directly use the picturePath
as src
, which would be the exact location of images.
Conclusion 🎇
Now that I understand what's the current logic of image uploads, and how to use the Cloudinary SDK, it is time to get to work and get it done 🐱💻
I'll be following up with a final blog for this series, once I have successfully integrated cloudinary with the project.
Stay Tuned 😎
Top comments (0)