ExpressJS:TypeError:无法读取未定义的属性“路径”尝试将文件上传到 cloudinary 并将 url 保存到 mongoDB

Posted

技术标签:

【中文标题】ExpressJS:TypeError:无法读取未定义的属性“路径”尝试将文件上传到 cloudinary 并将 url 保存到 mongoDB【英文标题】:ExpressJS: TypeError: Cannot read property 'path' of undefined When trying to upload a file to cloudinary and save the url to mongoDB 【发布时间】:2021-06-20 15:01:37 【问题描述】:

我正在尝试将文件上传到 cloudinary 并通过 POST 请求将 url 保存到 mongodb

我的前端代码如下所示:

         <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>

我在快递服务器上这个页面的路由:

//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')
    
)

但是在填写表单字段后尝试发布请求时,我收到错误:


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)

这里是我所有必需的导入和配置: 对于 utilscloudinary.js 文件夹中的 cloudinary 配置:

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

然后我将这个模块导入到 routes.js 文件中,如下所示:

const cloudinary = require("../utils/cloudinary");

请问我做错了什么?

PS:当我将我的 req.file 记录到控制台时,我变得未定义。

【问题讨论】:

从您的示例中,req.file 看起来是空的 - 您使用什么中间件来填充它?我猜想像multer?请注意,multer-storage-cloudinary 有助于自动将文件上传到 Cloudinary,但在这种情况下,您通常不会直接从您自己的代码中调用 Cloudinary 的 SDK(multer-storage-cloudinary 会隐含地为您执行此操作)。基于此,我认为您可能正在混合两种不同的集成方法 非常感谢@Igy,我可以通过使用 multer 中间件来填充 req.file 字段,然后再将任何数据放入其中来解决问题! 【参考方案1】:

问题解决了,显然我没有使用任何中间件(在这种情况下是 multer)来管理上传的文件。

代码sn-p

我必须在 utils 文件夹中创建一个 multer.js 文件

它将包含代码


    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);
      ,
    );

然后在 express 服务器文件夹中需要这个模块

const upload = require("../utils/multer");

然后在 add-product POST 请求中添加为中间件


    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')
        
    )

【讨论】:

以上是关于ExpressJS:TypeError:无法读取未定义的属性“路径”尝试将文件上传到 cloudinary 并将 url 保存到 mongoDB的主要内容,如果未能解决你的问题,请参考以下文章

ExpressJS:TypeError:无法读取未定义的属性“路径”尝试将文件上传到 cloudinary 并将 url 保存到 mongoDB

TypeError:无法读取未定义的属性“myDate”

TypeError:无法读取未定义的属性(读取“名称”)

TypeError:无法读取未定义的属性(读取“问题”)

TypeError:无法在 gitlab 中读取未定义的属性(读取“读取”)

TypeError:无法读取未定义的属性(读取“国家”)