Как загрузить файл с помощью multer или body-parser

Я новичок NodeJS, следуя книге "Веб-разработка с MongoDB и NodeJS". Я застрял в своей главе 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, пожалуйста, посмотрите, правильно ли я его использую, потому что он дает мне "body-parser revrecated" при запуске сервера. Я видел другие вопросы, такие как мои, и я следовал, но никто из них не работает.

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

Предполагаемый блок кода - это логика, которую я использую для загрузки файла. В ошибке это ссылается на "файл" как undefined, который находится в следующей строке функции saveImage. Он не может получить путь и, следовательно, выдает ошибку 500 в соответствии с другой частью функции saveImage. Почему здесь находится "файл" undefined? Я не понимаю.

var tempPath = req.files.file.path,

Ответ 1

multer() возвращает генератор промежуточного программного обеспечения, который использует указанные вами параметры, поэтому вы не можете передать его возвращаемое значение непосредственно на app.use(). Вы можете увидеть все типы промежуточного программного обеспечения, которые он может генерировать в документации, но обычно сгенерированное промежуточное ПО добавляется на уровне маршрута, а не во всем мире другие синтаксические анализаторы. Это связано с тем, что вы обычно передадите имя поля (ов) файла, которое вы ожидаете.

Например, это будет принимать один файл (вместе с любыми нефайловыми полями), имя поля формы которого 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 -capable, поэтому вы не можете использовать этот модуль для обработки загруженных файлов (ну, не дожидаясь передачи строки в кодировке base64 в форме application/x-www-form-urlencoded или что-то еще, но это намного менее эффективно).

Ответ 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);
});

Ответ 3

Код для загрузки файла с помощью Multer и сохранения его в локальной папке

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