如何使用multer或body-parser上传文件

时间:2016-03-24 14:29:03

标签: javascript node.js express multer body-parser

我是NodeJS的初学者,跟随着一本书"使用MongoDB和NodeJS进行Web开发"。我被困在第6章和'multer'。当我使用multer进行文件上传时,服务器会抛出以下错误:

/Users/fk / Documents / imageuploader / node_modules / express / lib / application.js: 209
throw new TypeError('app.use() requires middleware functions'); ^

TypeError: app.use() requires middleware functions

但是当我用bodyParser替换它时,服务器会启动,但是当我点击上传按钮时,它会在浏览器上显示以下错误。

500 TypeError: Cannot read property 'file' of undefined

但是,它应该将我重定向到另一个页面,其中显示上传的文件。

这是我的bodyParser代码,请查看我是否正确使用它,因为它给了我"身体解析器已弃用"在服务器的启动。我已经看到过像我这样的其他问题,但我没有注意到,但没有一个真的有用。

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

app.use(bodyParser({
  uploadDir: path.join(__dirname, '../public/upload/temp')
}));

以下代码显示我如何使用multer,以防万一我不应该做的事情请告诉我。如果上传文件,正文解析器或者multer,哪一个会更好?

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


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.files.file.path,
    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();

前面的代码块是我用来上传文件的逻辑。在错误中它指的是&#39; file&#39; as undefined,它位于saveImage函数的以下行中。它无法获取路径,因此根据saveImage函数的else部分抛出错误500。为什么&#39;文件&#39;在这里未定义?我不懂。

var tempPath = req.files.file.path,

4 个答案:

答案 0 :(得分:17)

multer()返回使用您指定的设置的中间件生成器,因此您无法将其返回值直接传递给app.use()。您可以在documentation中看到它可以生成的所有类型的中间件,但通常生成的中间件是在路由级别而不是像其他正文解析器一样全局添加的。这是因为您通常会传入您期望的文件字段的名称。

例如,这将接受表单字段名称为foo的单个文件(以及任何非文件字段):

var upload = multer({
  dest: path.join(__dirname, '../public/upload/temp')
});

// ...

app.post('/upload', upload.single('foo'), function(req, res) {
  if (req.file) {
    console.dir(req.file);
    return res.end('Thank you for the file');
  }
  res.end('Missing file');
});

此外,body-parser当前不会导出支持multipart/form-data的中间件,因此您无法使用该模块处理上传的文件(嗯,不能在{{1}中传递base64编码的字符串形式或东西,但效率低得多。)

答案 1 :(得分:9)

以下是MEAN中文件上传的基本代码,请检查

HTML

<form id="frmDoc" name="frmDocument" ng-submit="upload()" class="form-horizontal form-bordered" enctype="multipart/form-data" >
        <fieldset>
            <div class="form-group">
                <label class="col-md-4 control-label" for="val_email">Document<span class="text-danger">*</span></label>
                <div class="col-md-4">
                    <div class="input-group">
                    <input type="file" name="file" id='file' required="required" />
                    </div>
                </div>
            </div>
        </fieldset>
        <div class="form-group form-actions">
            <div class="col-md-8 col-md-offset-4">
                <button type="submit" class="btn btn-sm btn-primary"><i class="fa fa-upload"></i> submit</button>
            </div>
        </div>
    </form>

客户端代码

app.controller ('myctrl',function($scope,$http){

  $scope.upload = function () {
            var file = angular.element(document.querySelector('#file')).prop("files")[0];
                $scope.files = [];
                $scope.files.push(file);
                $http({
                    method: 'POST',
                    url: '/users/upload',
                    headers: { 'Content-Type': undefined },
                    transformRequest: function (data) {
                        var formData = new FormData();
                        formData.append('model', angular.toJson(data.model));
                        formData.append('file', data.files[0]);
                        return formData;
                    },
                    data: { model: { title: 'hello'}, files: $scope.files }

                }).success(function (res) {
                    console.log(res)
                });
        }


});

服务器端代码

var multer  = require('multer');
var mkdirp = require('mkdirp');

var storage = multer.diskStorage({
  destination: function (req, file, cb) {
    //var code = JSON.parse(req.body.model).empCode;
    var dest = 'public/uploads/';
    mkdirp(dest, function (err) {
        if (err) cb(err, dest);
        else cb(null, dest);
    });
  },
  filename: function (req, file, cb) {
    cb(null, Date.now()+'-'+file.originalname);
  }
});

var upload = multer({ storage: storage });

router.post('/upload', upload.any(), function(req , res){
    console.log(req.body);
    res.send(req.files);
});

答案 2 :(得分:0)

我更正了“使用MongoDB和NodeJS进行Web开发”这本书的代码,如下所示:

  import pandas as pd
    data = requests.get(url, timeout=5)
    entries = data.json()
    Header=entries['resultSet']['headers']
    data =entries['resultSet']['rowSet']
    filename='c:\\test\\NBA.xlsx'           

    df = pd.DataFrame.from_records(data)    
    df.columns=Header
    writer = pd.ExcelWriter(filename, engine='xlsxwriter')
    df.to_excel(writer, sheet_name='sheet1', index=False,startrow=0 , startcol=0)
    writer.save()

代码的其他部分保持不变。它有效,我可以上传图像文件。 最良好的祝愿, Mehrdad Sheikhan

答案 3 :(得分:-1)

使用Multer上传文件并将其保存到本地文件夹的代码

let multer = require('multer') // import library
let moment = require('moment')
let q = require('q')
let _ = require('underscore')

// Store file on local folder
let storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, 'public')
  },
filename: function (req, file, cb) {
let date = moment(moment.now()).format('YYYYMMDDHHMMSS')
cb(null, date + '_' + file.originalname.replace(/-/g, '_').replace(/ /g, '_'))
}
})

// Upload files
let upload = multer({ storage: storage }).array('files')
module.exports = {
fileUpload: function (req, res) {
let deferred = q.defer()
upload(req, res, function (err) {
      if (req.file === undefined && req.files === undefined) {
        deferred.resolve({ status: 200, message: 'File not attached', data:             
JSON.parse(req.body.body) })
      } else {
        if (err) {
          deferred.reject({ status: 400, message: 'error', data: err })
        } else {
          deferred.resolve({
            status: 200,
            message: 'File attached',
            filename: req.file ? req.file.filename : _.pluck(req.files,     
'filename'),
            data: JSON.parse(req.body.body)
          })
        }
      }
    })
    return deferred.promise
  }
}