I am trying to upload a file to cloudinary and save the url to mongodb via a POST request
Here's how my frontend code looks like:
<form action="/add-product?_csrf=<%=csrfToken%>" class="form-control col s12" method="POST" enctype="multipart/form-data">
<div class="row">
<div class="input-field">
<label for="title">Name</label>
<br>
<input type="text" id="name" name="name" required>
</div>
</div>
<div class="row">
<div>
<% if (categories.length > 0) { %>
<label for="category"><h5>Category</h5></label>
<select id="status" name="status">
<% categories.forEach(category => { %>
<option value="category"><%= category.category %></option>
<% }) %>
</select>
<% } else { %>
<p>There are no categories to select</p>
<% } %>
</div>
</div>
<div class="row">
<div class="input-field" id="ckeditor">
<h5>Product Description</h5>
<textarea id="body" name="description"></textarea>
</div>
</div>
<div class="row">
<div class="input-field">
<label for="image"> Upload Product Image</label>
<br>
<br>
<input type="file" name="image">
</div>
</div>
<div class="row">
<div class="input-field">
<label for="price">Price</label>
<br>
<input type="number" id="price" name="price">
</div>
</div>
<div class="row">
<input type="submit" value="Save" class="btn">
<a href="/" class="btn orange">Cancel</a>
</div>
</form>
My route for this page on the express server:
//get the link to add a product to the eccomerce application using a GET request
router.get('/add-product', ensureAuth, csrfProtection, async (req,res) =>{
try {
const categories = await Category.find().sort({createdAt:-1})
//console.log(categories)
res.render('addproduct',{categories:categories,csrfToken:req.csrfToken()})
} catch (err) {
console.error(err)
res.render('error/500')
}
})
//post the filled form
router.post('/add-product',ensureAuth, parseForm, csrfProtection,async (req,res)=>{
try {
// Upload image to cloudinary
console.log(req)
console.log(req.file)
const result = await cloudinary.uploader.upload(req.file.path, function(err,res){
console.error(err);
});
//assert the populate db relationship
req.body.user = req.user.id
let Product = new product({
category: req.body.category,
name: req.body.name,
image: result.secure_url,
description:req.body.description,
price:req.body.price,
})
await Product.save()
res.redirect('/')
} catch (err) {
console.error(err)
res.render('error/500')
}
})
However when trying to post the request after filling the form fields, i get the error:
undefined
TypeError: Cannot read property 'path' of undefined
at router.post (/home/e-wave/Desktop/nodecommerce/routes/eroutes.js:131:62)
at Layer.handle [as handle_request] (/home/e-wave/Desktop/nodecommerce/node_modules/express/lib/router/layer.js:95:5)
at next (/home/e-wave/Desktop/nodecommerce/node_modules/express/lib/router/route.js:137:13)
at csrf (/home/e-wave/Desktop/nodecommerce/node_modules/csurf/index.js:117:5)
at Layer.handle [as handle_request] (/home/e-wave/Desktop/nodecommerce/node_modules/express/lib/router/layer.js:95:5)
at next (/home/e-wave/Desktop/nodecommerce/node_modules/express/lib/router/route.js:137:13)
at urlencodedParser (/home/e-wave/Desktop/nodecommerce/node_modules/body-parser/lib/types/urlencoded.js:100:7)
at Layer.handle [as handle_request] (/home/e-wave/Desktop/nodecommerce/node_modules/express/lib/router/layer.js:95:5)
at next (/home/e-wave/Desktop/nodecommerce/node_modules/express/lib/router/route.js:137:13)
at ensureAuth (/home/e-wave/Desktop/nodecommerce/middleware/auth.js:4:20)
at Layer.handle [as handle_request] (/home/e-wave/Desktop/nodecommerce/node_modules/express/lib/router/layer.js:95:5)
at next (/home/e-wave/Desktop/nodecommerce/node_modules/express/lib/router/route.js:137:13)
at Route.dispatch (/home/e-wave/Desktop/nodecommerce/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/home/e-wave/Desktop/nodecommerce/node_modules/express/lib/router/layer.js:95:5)
at /home/e-wave/Desktop/nodecommerce/node_modules/express/lib/router/index.js:281:22
at Function.process_params (/home/e-wave/Desktop/nodecommerce/node_modules/express/lib/router/index.js:335:12)
Here all my neccesary imports and config: For cloudinary config in the utils and cloudinary.js folder:
const cloudinary = require("cloudinary").v2;
const {cloudStorage} = require('multer-storage-cloudinary');
const dotenv = require('dotenv').config({path:__dirname+'/.env'});
cloudinary.config({
cloud_name: process.env.CLOUD_NAME,
api_key: process.env.API_KEY,
api_secret: process.env.API_SECRET,
});
module.exports = cloudinary
Then i imported this module into the routes.js file like this:
const cloudinary = require("../utils/cloudinary");
Please what could i be doing wrong?
PS:When i logged my req.file to the console, i was getting undefined.
Problem Solved, apparently i didn't using any middleware (which was multer in this case) to manage the uploaded files.
code snippet
i had to create a multer.js file in the utils folder
it will contain the code
const multer = require("multer");
const path = require("path");
// Multer config
module.exports = multer({
storage: multer.diskStorage({}),
fileFilter: (req, file, cb) => {
let ext = path.extname(file.originalname);
if (ext !== ".jpg" && ext !== ".jpeg" && ext !== ".png") {
cb(new Error("File type is not supported"), false);
return;
}
cb(null, true);
},
});
then require this module in the express server folder
const upload = require("../utils/multer");
then add as a middleware in the add-product POST request
router.post('/add-product', upload.single("image"),ensureAuth, parseForm, csrfProtection,async (req,res)=>{
try {
// Upload image to cloudinary
const result = await cloudinary.uploader.upload(req.file.path);
//assert the populate db relationship
req.body.user = req.user.id
let Product = new product({
category: req.body.category,
name: req.body.name,
image: result.secure_url,
description:req.body.description,
price:req.body.price,
})
await Product.save()
res.redirect('/')
} catch (err) {
console.error(err)
res.render('error/500')
}
})
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.