【问题标题】:Node.js TypeError: Cannot read property 'file' of undefinedNode.js TypeError:无法读取未定义的属性“文件”
【发布时间】:2016-05-12 03:32:47
【问题描述】:

我刚刚学习 node.js,很难使用 express 和 multer 进行简单的文件上传。

这是表格:

上传图片

在我的configure.js 我有:

app.use(express.static(path.join(__dirname, 'public')));
app.use(multer({dest:'../public/upload/temp'}).single('file'));

还有image.js 控制器:

create: function(req, res) {
        var saveImage = function() {
            console.log(req.body);
            var possible = 'abcdefghijklmnopqrstuvwxyz0123456789',
                imgUrl = '';

            for(var i=0; i < 6; i+=1) {
                imgUrl += possible.charAt(Math.floor(Math.random() * possible.length));
            }

            var tempPath = req.files.file.path, //<line 55 error
                ext = path.extname(req.files.file.name).toLowerCase(),
                targetPath = path.resolve('./public/upload/' + imgUrl + ext);

            if (ext === '.png' || ext === '.jpg' || ext === '.jpeg' || ext === '.gif') {


                fs.rename(tempPath, targetPath, function(err) {
                    if (err) throw err;

                    res.redirect('/images/' + imgUrl);
                });
            } else {
                fs.unlink(tempPath, function () {
                    if (err) throw err;

                    res.json(500, {error: 'Only image files are allowed.'});
                });
            }
        };

        saveImage();
    },

但是,当我尝试上传图片时出现此错误:

TypeError: Cannot read property 'file' of undefined
    at saveImage (/home/pc/node-dev/test-proj/controllers/image.js:55:37)
    at module.exports.create (/home/pc/node-dev/test-proj/controllers/image.js:76:9)
    at Layer.handle [as handle_request] (/home/pc/node-dev/test-proj/node_modules/express/lib/router/layer.js:95:5)
    at next (/home/pc/node-dev/test-proj/node_modules/express/lib/router/route.js:131:13)
    at Route.dispatch (/home/pc/node-dev/test-proj/node_modules/express/lib/router/route.js:112:3)
    at Layer.handle [as handle_request] (/home/pc/node-dev/test-proj/node_modules/express/lib/router/layer.js:95:5)
    at /home/pc/node-dev/test-proj/node_modules/express/lib/router/index.js:277:22
    at Function.process_params (/home/pc/node-dev/test-proj/node_modules/express/lib/router/index.js:330:12)
    at next (/home/pc/node-dev/test-proj/node_modules/express/lib/router/index.js:271:10)
    at urlencodedParser (/home/pc/node-dev/test-proj/node_modules/body-parser/lib/types/urlencoded.js:95:37)

当我记录 req 对象时,file 不存在:

{ title: 'myimage', description: 'something' }

其实 sn-p 只是我在this book 中读到的稍微修改过的版本,它使用的是过时的 express-3。所以基本上我只是用multer 部分更新了它。

我想知道这里出了什么问题以及如何解决它。

【问题讨论】:

  • 你有没有用 multer 找到一个可行的解决方案?我尝试了下面列出的修复程序,并将其更改为 req.file 和 req.path 似乎有效,但现在书中的示例重定向到 /image/ 路由而没有成功命名或接收文件。
  • 你 var tempPath = req.file.path; var ext = path.extname(req.file.originalname).toLowerCase(); var targetPath = path.resolve('./public/upload/' + imgUrl + ext);

标签: node.js express multer multifile-uploader


【解决方案1】:

从上面引用的同一本书中,这是 2021 年,上面的所有代码都失败了,我已经为此奋斗了 4 多天,终于破解了它。我将 multer 中间件移到了路由模块中以使其工作

将 routes.js 更新为

    var express = require('express'),
 path = require('path'),
 router = express.Router(),
 home = require('../controllers/home'),
 image = require('../controllers/image');
 const multer  = require('multer')
const upload = multer({ dest: path.join(__dirname,
    'public/upload/temp')});
module.exports = function(app) {
 router.get('/', home.index);
 router.get('/images/:image_id', image.index);
 router.post('/images',upload.single('image'), image.create);
 router.post('/images/:image_id/like', image.like);
 router.post('/images/:image_id/comment', image.comment);
 app.use(router);
};

将图像控制器中的创建函数更新为

create: function (req, res) {
    var saveImage = function () {
      var possible = "abcdefghijklmnopqrstuvwxyz0123456789",
        imgUrl = "";
      for (var i = 0; i < 6; i += 1) {
        imgUrl += possible.charAt(Math.floor(Math.random() * possible.length));
      }

      var tempPath = req.file.path,
        ext = path.extname(req.file.originalname).toLowerCase(),
        targetPath = path.resolve("./public/upload/" + imgUrl + ext);
      if (
        ext === ".png" ||
        ext === ".jpg" ||
        ext === ".jpeg" ||
        ext === ".gif"
      ) {
        fs.rename(tempPath, targetPath, function (err) {
          if (err) throw err;
          res.redirect("/images/" + imgUrl);
        });
      } else {
        fs.unlink(tempPath, function () {
          if (err) throw err;
          res.json(500, { error: "Only image files are allowed." });
        });
      }
    };
    saveImage();
  }

从 configure.js 模块中注释掉或删除 multer 中间件

//app.use(multer({ dest: path.join(__dirname, 'public/upload/temp')}).single('image'));

确保您在 index.handlebars 中的表单与此相对应

<form method="post" action="/images" enctype="multipart/form-data" >
        <div class="panel-body form-horizontal">
            <div class="form-group col-md-12">
                <label class="col-sm-2 control-label" for="file">Browse:</label>
                <div class="col-md-10">
                    <input class="form-control" type="file" name="image" id="file">
                </div>
            </div>
            <div class="form-group col-md-12">
                <label class="col-md-2 control-label" for="title">Title:</label>
                <div class="col-md-10">
                    <input class="form-control" type="text" name="title">
                </div>
            </div>
            <div class="form-group col-md-12">
                <label class="col-md-2 control-label" for="description">Description:</label>
                <div class="col-md-10">
                    <textarea class="form-control" name="description" rows="2"></textarea>
                </div>
            </div>
            <div class="form-group col-md-12">
                <div class="col-md-12 text-right">
                    <button type="submit" id="login-btn" class="btn btn-success" type="button">
                        <i class="fa fa-cloud-upload ">
                        </i> Upload Image</button>
                </div>
            </div>
        </div>
    </form>

【讨论】:

    【解决方案2】:

    从上面提到的同一个book,我能够在登录到控制台req.files.file和从控制台的详细信息中找到一个有效的解决方案path存在于file对象和它是tempFilePath 而不是path,所以实际路径是var tempPath = req.files.file.tempFilePath;。以及完整的代码

    create: function(req, res){
        var saveImage = function(){
          var possible = 'abcdefghijklmnopqrstuvwxyz0123456789';
          var imgUrl = '';
    
          for(var i=0; i<6; i++){
            imgUrl += possible.charAt(Math.floor(Math.random()*possible.length));
          }
    
         // if (!req.file) return console.log('Please upload a file')
         console.log(req.files.file)
         //
          var tempPath = req.files.file.tempFilePath;
          var ext = path.extname(req.files.file.name).toLowerCase();
          var targetPath = path.resolve('./public/upload/' + imgUrl + ext);
    
          if(ext === '.png' || ext === '.jpg' || ext === '.jpeg' || ext === '.gif'){
            fs.rename(tempPath, targetPath, function(err){
              if(err) throw err;
    
              res.redirect('/images/' +imgUrl);
            });
          } else {
            fs.unlink(tempPath, function(){
              if(err) throw err;
    
              res.json(500, {error: 'Only image files are allowed'});
            })
          }
        }
        saveImage();
      }

    The details to the console after logging the req.files.file

    【讨论】:

      【解决方案3】:

      您正在使用upload.single,您应该使用req.file 而不是req.files。要上传多个文件,请使用upload.array

      请注意,您不需要在 req.file 之后再添加一个 .file。如果您使用的是upload.singlereq.file 是上传的文件。

      【讨论】:

      • 感谢您的提示。但是现在我使用tempPath = req.file.file.path, 会导致TypeError: Cannot read property 'path' of undefined 错误。有什么想法吗?
      • @qliq as stated in document,你只需要使用req.file.path,而不是req.file.file.path。 (来自文档:单个文件将存储在req.file。)
      猜你喜欢
      • 2020-05-15
      • 2021-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-03
      • 2021-05-11
      • 2020-11-03
      • 2020-05-13
      相关资源
      最近更新 更多