【问题标题】:How to upload file using multer or body-parser如何使用 multer 或 body-parser 上传文件
【发布时间】:2016-07-12 04:29:20
【问题描述】:

我是一名 NodeJS 初学者,正在阅读《使用 MongoDB 和 NodeJS 进行 Web 开发》一书。我被“multer”困在第6章。当我使用 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 代码,请查看我是否正确使用它,因为它在服务器启动时给了我“body-parser deprecated”。我见过像我这样的其他问题,我也关注过,但它们都没有真正起作用。

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

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

以下代码显示了我如何使用 multer,以防万一有什么我不应该做的事情,请告诉我。在上传文件的情况下,body-parser 或 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();

前面的代码块是我用来上传文件的逻辑。在错误中,它在 saveImage 函数的以下行中将“文件”称为未定义。它无法获取路径,因此根据 saveImage 函数的 else 部分抛出错误 500。为什么“文件”在这里未定义?我不明白。

var tempPath = req.files.file.path,

【问题讨论】:

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


【解决方案1】:

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 的中间件,因此您不能使用该模块来处理上传的文件(好吧,没有以application/x-www-form-urlencoded 形式传递base64 编码的字符串或其他东西,但效率要低得多)。

【讨论】:

    【解决方案2】:

    这是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);
    });
    

    【讨论】:

    • 嗨,如果我想发送多个文件,我需要对 $http 函数内的 angular transformRequest 函数进行哪些更改
    • 循环遍历所有文件输入并将每个文件附加到 formData 上,如下所示。 for( 让 i=0 ; i
    • 我正在尝试使用您的代码从邮递员上传我的图片。但文件未保存在上传目录中。任何帮助...谢谢
    【解决方案3】:

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

    api- call fileUpload function
    fileUpload(req)
        .then(uploadRes => {
            console.log('uploadRes', uploadRes)
        })
        .catch(err => {
            console.log('err', err)
        })
    
    
    Create file upload service
    const multer = require('multer') // import library
    const moment = require('moment')
    const q = require('q')
    const _ = require('underscore')
    const fs = require('fs')
    let dir = './public'
    
    /** Store file on local folder */
    let storage = multer.diskStorage({
        destination: function (req, file, cb) {
            cb(null, dir)
        },
        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')
    
    /** Exports fileUpload function */
    module.exports = {
        fileUpload: function (req) {
            let deferred = q.defer()
    
            /** Create dir if not exist */
            if (!fs.existsSync(dir)) {
                fs.mkdirSync(dir)
                console.log(`\n\n ${dir} dose not exist, hence created \n\n`)
            }
    
            upload(req, {}, function (err) {
                if (req && (_.isEmpty(req.files))) {
                    deferred.resolve({ status: 200, message: 'File not attached', data: [] })
                } else {
                    if (err) {
                        deferred.reject({ status: 400, message: 'error', data: err })
                    } else {
                        deferred.resolve({
                            status: 200,
                            message: 'File attached',
                            filename: _.pluck(req.files,
                                'filename'),
                            data: req.files
                        })
                    }
                }
            })
            return deferred.promise
        }
    }
    

    【讨论】:

      【解决方案4】:

      我将《Web Development with MongoDB and NodeJS》一书的代码更正如下:

      app.use(multer({dest:path.join(__dirname,'../public/upload/temp')}).any());
      .
      .
      .
      .
      const tempPath = req.files[0].path,  // Temporary location of uploaded file
      ext = path.extname(req.files[0].originalname).toLowerCase(), // Get file extension of the uploaded file
      targetPath = path.resolve(`./public/upload/${imgUrl}${ ext}`); // The final path for the image file
      
      
      

      代码的其他部分保持不变。它有效,我可以上传图像文件。 最良好的祝愿, 迈赫达德·谢汗

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-05-14
        • 1970-01-01
        • 2019-07-31
        • 1970-01-01
        • 2020-12-31
        • 1970-01-01
        相关资源
        最近更新 更多