Node.js TypeError: Cannot read property 'file' of undefined

Node.js TypeError: Cannot read property 'file' of undefined

我刚刚开始学习 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' }

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

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

您正在使用 upload.single, which you should use req.file not req.files. To upload multiple files, use upload.array

请注意,在 req.file 之后您不需要另一个 .file。如果您使用 upload.single.

,则 req.file 是上传的文件

根据上面引用的相同 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

来自上面引用的同一本书,这是 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>