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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36202618/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 18:45:12  来源:igfitidea点击:

How to upload file using multer or body-parser

javascriptnode.jsexpressmulterbody-parser

提问by Farooq Khan

I am a NodeJS beginner, following along a book "Web Development with MongoDB and NodeJS". I am stuck at its chapter 6 with 'multer'. When I use multer for file uploads the server throws the following error:

我是一名 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

but when I replace it with bodyParser the server fires up but when I click the upload button it gives me the following error on the browser.

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

500 TypeError: Cannot read property 'file' of undefined

However, it is supposed to redirect me towards another page, where the uploaded file is shown.

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

Here is my bodyParser code, please see if I am using it correctly because it gives me "body-parser deprecated" at the starting of the server. I've seen other questions like mine and I followed but none of them really work.

这是我的 bodyParser 代码,请查看我是否正确使用它,因为它在服务器启动时给了我“body-parser deprecated”。我见过像我这样的其他问题,我也遵循了,但没有一个真正有效。

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

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

Following code shows how I use multer, just in case if there is something I shouldn't be doing please let me know. Which one would be better in case of uploading files, body-parser or multer?

以下代码显示了我如何使用 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();

Preceding block of code is the logic that I am using to upload the file. In the error it is referring to 'file' as undefined which is in the following line in the saveImage function. It is unable to get the path and therefore throws error 500 according to the else part of the saveImage function. Why is 'file' undefined here? I dont get it.

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

var tempPath = req.files.file.path,

回答by mscdex

multer()returns a middleware generator that uses the settings you specified, so you cannot pass its return value directly to app.use(). You can see all of the types of middleware it can generate in the documentation, but typically the generated middleware are added at the route level instead of globally like the other body parsers. This is because you will typically pass in the name of the file field(s) that you will be expecting.

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

For example, this will accept a single file (along with any non-file fields) whose form field name is foo:

例如,这将接受单个文件(以及任何非文件字段),其表单字段名称为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');
});

Also, body-parserdoes not currently export a multipart/form-data-capable middleware, so you cannot use that module for handling uploaded files (well, short of passing a base64-encoded string in an application/x-www-form-urlencodedform or something, but that's much less efficient).

此外,body-parser当前不导出具有功能的multipart/form-data中间件,因此您不能使用该模块来处理上传的文件(好吧,缺少以application/x-www-form-urlencoded表单或其他形式传递 base64 编码的字符串,但效率要低得多)。

回答by Ashutosh Jha

Here is the basic code for file upload in MEAN please check

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

HTML

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>


CLIENT SIDE CODE

客户端代码

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


});


SERVER SIDE CODE

服务器端代码

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

回答by Rohit Parte

Code for upload file using Multer and save it to local folder

使用 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
    }
}