Suppose you want to upload a user avatar to cloudinary and store the url to your database.
In Backend-
1.Create a cloudinary.js and multer.js file.
CLOUD_NAME, CLOUD_API_KEY, CLOUD_API_SECRET will be provided once you sign up on cloudinary.
cloudinary.js-
const cloudinary = require("cloudinary").v2;
const path = require("path");
require("dotenv").config({
path: path.resolve(__dirname, "../config/config.env"),});
cloudinary.config({
cloud_name: process.env.CLOUD_NAME,
api_key: process.env.CLOUD_API_KEY,
api_secret: process.env.CLOUD_API_SECRET,});
module.exports=cloudinary
multer.js-
const Multer = require("multer");
const storage = new Multer.memoryStorage();
const upload = Multer({storage});
module.exports=upload
2. in userRoutes-
we're sending userName and avatar from frontend. Both of the names should match with what's given in the schema of user.
const router=express.Router()
const upload = require("./../utils/multer");
router.route("/registerUser").post(
upload.fields([
{ name: "userName", maxCount: 1 },
{ name: "avatar", maxCount: 1 },])
userController.registerUser);
3. in userController-
const cloudinary = require("./../utils/cloudinary.js");
const streamifier = require("streamifier");
//upload avatar to cloudinary
const bufferStream=streamifier.createReadStream(req.files.avatar[0].buffer)
const result = await new Promise((resolve, reject) => {
const cloudStream = cloudinary.uploader.upload_stream(
{ folder: "BuyBud/users" },
(error, result) => {
if (error) {reject(error)}
else {resolve(result)}});
bufferStream.pipe(cloudStream) // Pipe the buffer stream to the cloudinary upload stream
}) ;
let avatar = {
public_id: result.public_id,
url: result.url,}
you can now send the userName and avatar to be saved in database
user = new User({
userName,
avatar});
await user.save();
for multiple images-
let imageUrls = [];
const { title, description, price, category, stock } = req.body;
for (let i = 0; i < req.files.imageUrls.length; i++) {
const bufferStream = streamifier.createReadStream(
req.files.imageUrls[i].buffer
); // Create a readable stream from the buffer
const result = await new Promise((resolve, reject) => {
const cloudStream = cloudinary.uploader.upload_stream(
{ folder: "BuyBud/products" },
(error, result) => {
if (error) {reject(error)}
else {resolve(result)}});
bufferStream.pipe(cloudStream); // Pipe the buffer stream to the cloudinary upload stream
})
imageUrls.push({
public_id: result.public_id,
url: result.url})}
In Frontend-
4. In your react component-
in return statement, provide space for user to upload the image-
<label>Avatar:</label>
<input type="file" onChange={handleAvatarUpload} /> (add multiple for image array)
above return statement, handle the logic to send the avatar to backend.
set the avatar to avatar variable
const [avatar, setAvatar] = useState(null);
const handleAvatarUpload = (e) => {
setAvatar(e.target.files)};
use axios to send formData to request url. The name `avatar` should be the same as backend.
let formData = new FormData();
formData.append("userName", userName);
formData.append(`avatar`, avatar);
const response = await axios.post("/api/registerUser", formData, {
headers: {
"Content-Type": "multipart/form-data"}});
for array- (`imageUrls`) name should be the same as is in the backend
let handleImageUpload=(e)=>{
setImageFiles(e.target.files)}
for (let i = 0; i < imageFiles.length; i++) {formData.append(`imageUrls`, imageFiles[i])}