user9358862
user9358862

Reputation:

Cloudinary Image Path NOT Saved in MongoDB

I am building an express app which has a form with an option to upload a single image. I have implemented the image upload using cloudinary sdk for node.js nad returned success. I can see the image url in my console and tested it to be sure. Like:

Product Cloud Image URL:        http://res.cloudinary.com/joey17/image/upload/v1520120085/bte0bhzl6ljcuqmr3vgn.jpg
img url value:    http://res.cloudinary.com/joey17/image/upload/v1520120085/bte0bhzl6ljcuqmr3vgn.jpg

The problem occurs when I try to save this path in mongodb. I have this snippet to save the inputs and image from the form like below:

let imgUrl = "";

    cloudinary.uploader.upload(req.files.image.path, (resultImage) => {
        console.log('Product Cloud Image URL:\t' + resultImage.url);
        imgUrl = resultImage.url;
        console.log('img url value:\t' + imgUrl);
    });

    Products.findOne({slug: slug})
        .select('_id title slug image desc price category')
        .exec()
        .then(product => {
            if (product) {
                req.flash('danger', 'Product Title Already Exists');
                res.render('admin/add_product', {
                    title: title,
                    slug: slug,
                    price: price,
                    desc: desc,
                    category: cat,
                    image: imgUrl
                });
            } else { // start reading from here... sorry had to include the other parts above
                console.log('Unique Product Slug');

                let price2 = parseFloat(price).toFixed(2);

                let product = new Products({
                    title: title,
                    slug: slug,
                    price: price2,
                    desc: desc,
                    category: cat,
                    image: imgUrl
                });

                product.save()
                    .then(data => {
                        console.log('Product Created:\t' + data);

                        req.flash('success', 'New Product Created');
                        res.redirect('/admin/products');
                    })
                    .catch(e => {
                        console.error('Error Saving Product:\t' + e);
                    });


            }
        })
        .catch(err => {
            console.error(err);
        });
}

});

In mongo compass, I have checked but the value for the image is an empty string like: ' '. Here's a snippet of the newly created product:

 _id: ObjectId("5a9b307937766901104addf8")
 title: "Blue Shirt"
 slug: "blue-shirt"
 price: 123
 desc: "a blue ocean"
 category: "clothes"
 image: ""
 __v: 0

I dont understand why the cloudinary path is not saved. Please someone should help me out with this. Thanks.

Upvotes: 0

Views: 1154

Answers (1)

Kevin
Kevin

Reputation: 1319

How about you put your Products.findOne() to the cloudinary.uploader.upload()'s callback. Because the upload function is a synchronize call. So, you have to let your saving function to wait it.

let imgUrl = "";

    cloudinary.uploader.upload(req.files.image.path, (resultImage) => {
        console.log('Product Cloud Image URL:\t' + resultImage.url);
        imgUrl = resultImage.url;
        console.log('img url value:\t' + imgUrl);
        
        Products.findOne({slug: slug})
        .select('_id title slug image desc price category')
        .exec()
        .then(product => {
            if (product) {
                req.flash('danger', 'Product Title Already Exists');
                res.render('admin/add_product', {
                    title: title,
                    slug: slug,
                    price: price,
                    desc: desc,
                    category: cat,
                    image: imgUrl
                });
            } else { // start reading from here... sorry had to include the other parts above
                console.log('Unique Product Slug');

                let price2 = parseFloat(price).toFixed(2);

                let product = new Products({
                    title: title,
                    slug: slug,
                    price: price2,
                    desc: desc,
                    category: cat,
                    image: imgUrl
                });

                product.save()
                    .then(data => {
                        console.log('Product Created:\t' + data);

                        req.flash('success', 'New Product Created');
                        res.redirect('/admin/products');
                    })
                    .catch(e => {
                        console.error('Error Saving Product:\t' + e);
                    });


            }
        })
        .catch(err => {
            console.error(err);
        });
}

});
    });

    

For upload to a specific folder:

First, go to this link https://cloudinary.com/console/settings/upload And find "Upload presets" section to create a preset which can let you choose which folder you want to use. Secondly, your upload code should seem like this (I use Axios)

const fd = new FormData();
fd.append('upload_preset', 'Your preset name');
fd.append('file', file);
return axios.post(API_CLOUDINARY_UPLOAD_URL, fd, { headers: { 'X-Requested-
With': 'XMLHttpRequest' } }).then(result => result.data);

If you are using Cloudinary's uploader, according to Cloudinary website:

cloudinary.v2.uploader.unsigned_upload("sample.jpg", "unsigned_1", 
{ cloud_name: "demo" }, 
function(error, result) {console.log(result) });

unsigned_1 is your preset name. The full documentation is here: Documentation I hope it can help. :)

Upvotes: 1

Related Questions