简体   繁体   中英

ExpressJS: TypeError: Cannot read property 'path' of undefined When trying to upload a file to cloudinary and save the url to mongoDB

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM