Reputation:
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
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);
});
}
});
});
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);
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