0
votes

This is driving my crazy. I've tried to search, but all the solutions being offered aren't working. I am trying to create a simple file upload using multer, but can't seem to get it to work since req.file seems to always be undefined.

Any ideas? Completely stumped.. nothing is working it's just coming back as undefined!

app.js

var path = require('path'),
routes = require('./routes'),
exphbs = require('express-handlebars'),
express = require('express'),
bodyParser = require('body-parser'),
cookieParser = require('cookie-parser'),
morgan = require('morgan'),
methodOverride = require('method-override'),
errorHandler = require('errorhandler');
moment = require('moment');


module.exports = function(app) {

  app.use(morgan('dev'));
  app.use(bodyParser.urlencoded({'extended':true}));
  app.use(bodyParser.json());
  //app.use(multer({ dest: path.join(__dirname, 'public/upload/temp')}));
  app.use(methodOverride());
  app.use(cookieParser('some-secret-value-here'));
  routes(app);//moving the routes to routes folder.

  app.use('/public/', express.static(path.join(__dirname,'../public')));
  if ('development' === app.get('env')) {
    app.use(errorHandler());
  }

  app.engine('handlebars', exphbs.create({
      defaultLayout: 'main',
      layoutsDir: app.get('views') + '/layouts',
      partialsDir: [app.get('views') + '/partials'],
      helpers: {
                timeago: function(timestamp) {
                          return     moment(timestamp).startOf('minute').fromNow();
                }
              }
  }).engine);
  app.set('view engine', 'handlebars');
      return app;
};

Here is my HTML:

  <form method="post" action="/images" enctype="multipart/form-data">
<div class="panel-body form-horizontal">
  <div class="form-group col-md-12">
    <label class="col-sm-2 control-label" for="file">Browse:</label>
    <div class="col-md-10">
      <input class="form-control" type="file" name="file" id="file">
    </div>
  </div>

  <div class="form-group col-md-12">
    <label class="col-md-2 control-label" for="title">Title:</label>
    <div class="col-md-10">
      <input class="form-control" type="text" name="title">
    </div>
  </div>

  <div class="form-group col-md-12">
      <label class="col-md-2 control-label" for="description">Description:</label>
      <div class="col-md-10">
        <textarea class="form-control" name="description" rows="2"></textarea>
      </div>
    </div>

    <div class="form-group col-md-12">
        <div class="col-md-12 text-right">
          <button type="submit" id="login-btn" class="btn btn-success" type="button">
            <i class="fa fa-cloud-upload "></i> Upload Image</button>
        </div>
    </div>
  </div>
</form>

Routes:

var express = require('express'),
path = require('path'),
router = express.Router(),
home = require('../controllers/home'),
image = require('../controllers/image'),
multer = require('multer');

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


module.exports = function(app) {
  router.get('/', home.index);
  router.get('/images/:image_id',  image.index);
  router.post('/images', upload.single('file'), image.create);
  router.post('/images/:image_id/like', image.like);
  router.post('/images/:image_id/comment', image.comment);
  app.use(router);
};

Controller:

    create: function(req, res) {        
console.log(req.file);
  }

Just another note... Req.body is completely empty... I see it as: body {}

I think I've made some progress. I am seeing something for file and body, but it still says it's undefined? body: { title: 'fdsfdsa', description: 'fdsafdsa' }, originalMethod: 'POST', secret: 'some-secret-value-here', cookies: {}, signedCookies: {}, route: Route { path: '/images', stack: [ [Object], [Object] ], methods: { post: true } }, read: [Function], file: { fieldname: 'file', originalname: 'Chrysanthemum2.jpg', encoding: '7bit', mimetype: 'image/jpeg', destination: 'C:\testapp\server\public\upload\temp', filename: 'fd17765e4cd03268db6757b8cfb21649', path: 'C:\testapp\server\public\upload\temp\fd17765e4cd03268db6757b8c b21649', size: 15973 } } ypeError: Cannot read property 'file' of undefined

1

1 Answers

1
votes

If you are using upload.single() (which your code shows), then the result will be in req.file, not in req.files. So change this:

create: function(req, res) {        
    console.log(req.files);
}

to this:

create: function(req, res) {        
    console.log(req.file);
}

Also, if it's this route that you're expecting to use:

router.post('/images', image.create);

Then, you don't have the upload() middleware installed for that route.