【问题标题】:Express 3.4.8 Photo uploading issue - how to solve without using bodyParser()?Express 3.4.8 图片上传问题——不使用bodyParser()如何解决?
【发布时间】:2025-11-30 05:25:02
【问题描述】:

我在 Gist 的代码: https://gist.github.com/yhagio/10654836

我是 Express 的新手,从“Node.js in Action - Chapter.9”一书的示例(上传照片)中尝试过。 作者用的是Express版本“3.4.0”,但我用的是“3.4.8”,遇到了这个问题,

我尝试上传图片时的错误消息:

500 TypeError: Cannot read property 'photo' of undefined

routes/photos.js

...
exports.submit = function (dir) {
  return function (req, res, next) {
    var img = req.files.photo.image; // ---- This 'photo' part is undefined
    var name = req.body.photo.name || img.name;
    var path = join(dir, img.name);

    fs.rename(img.path, path, function (err) {
      if (err) { return next(err); };

      Photo.create({
          name:name,
          path:req.name
        }, function (err) {
        if (err) { return next(err); };
        res.redirect('/');
      });
    });
  };
}; 

但我发现在我的 app.js 中(从 3.4.8 开始不再使用 bodyParser())

app.js(在我的代码 Express 3.4.8 中)

...
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());       // Instead of bodyParser()
app.use(express.urlencoded()); // Instead of bodyParser()
...

但是在作者的代码中有bodyParser()。

app.js(作者使用 Express 3.4.0

...
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser()); // This is no longer used in latest version

所以,我想知道是否可以通过使用 multer (http://expressjs-book.com/forums/topic/replacement-for-bodyparser-connect-multipart/) 来解决此问题:

app.use(express.json());       
app.use(express.urlencoded());
app.use(multer({ dest: './public/photos' })); // I tried this

这没有解决。请帮我。谢谢。

更新:我想出的解决方案

此代码有效(routes/photos.js)

exports.submit = function (dir) {
  return function(req, res, next){
    var form = new multiparty.Form();
    form.parse(req, function(err, fields, files){
      var img = files.image[0];
      var name = fields.name || img.originalFilename;
      var path = join(dir, img.originalFilename);
      fs.rename(img.path, path, function(err){
        if(err){return next(err); };
        Photo.create({
          name: name,
          path: img.originalFilename
        }, function(err){
          if(err){return next(err); };
          res.redirect('/');
        });
      });
    });
  };
}; 

【问题讨论】:

  • 您已将文件输入命名为photo[name],并且您正在寻找req.body.photo,而且req.files 应该包含上传的文件,为什么它会是一个带有photo 的对象财产?这里似乎有很多差异?
  • req.body.photo.name || img.name 如果从表单上传时未命名,则默认为原始文件名。而req.files 获取上传文件(图像),所以我认为这里似乎没问题,但我不确定这部分是否会导致问题:(
  • 你应该在 Manning 论坛上发布这本书 manning-sandbox.com/forum.jspa?forumID=790

标签: node.js file-upload express mongoose middleware


【解决方案1】:

您尝试过node-multiparty 吗?以下是 README 中的示例用法:

var multiparty = require('multiparty')
  , http = require('http')
  , util = require('util')

http.createServer(function(req, res) {
  if (req.url === '/upload' && req.method === 'POST') {
    // parse a file upload
    var form = new multiparty.Form();

    form.parse(req, function(err, fields, files) {
      res.writeHead(200, {'content-type': 'text/plain'});
      res.write('received upload:\n\n');
      res.end(util.inspect({fields: fields, files: files}));
    });

    return;
  }

  // show a file upload form
  res.writeHead(200, {'content-type': 'text/html'});
  res.end(
    '<form action="/upload" enctype="multipart/form-data" method="post">'+
    '<input type="text" name="title"><br>'+
    '<input type="file" name="upload" multiple="multiple"><br>'+
    '<input type="submit" value="Upload">'+
    '</form>'
  );
}).listen(8080);

作者(Andrew Kelley)recommends 避免使用 bodyParser,所以您可以避免使用它,但多方似乎为我解决了类似的问题。

【讨论】:

  • 感谢@kentcdodds,我设法弄清楚使用多方:) 解决方案已更新!
  • @Yuichi 真棒!确保接受答案,以便将来的 Google 搜索者更轻松地找到它。
  • 这实际上并没有回答问题。相反,它提供了一种替代解决方案。请参阅我对初始查询的直接回复。
【解决方案2】:

它不再起作用的原因是 node-formidable 库不再包含在 Express 中。如果您想继续使用 formidable,请按照以下说明操作。

在 Express 4.x 中使用 body-parser 的正确方法是:

var express = require('express'),
    bodyParser = require('body-parser'),
    app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

访问文件:

var formidable = require('formidable'),
    form = new formidable.IncomingForm();

exports.submit = function (dir) {
    return function (req, res, next) {
        form.parse(req, function(err, fields, files) {
            // The files object here is what you expected from req.files
        });
    });
});

注意:如果您尝试使用多个,请设置:

form.multiples = true;

【讨论】: