Search code examples
javascriptnode.jsfile-uploadexpressbusboy

file upload in express js giving problems again


Though I have read quite a few questions being answered on stackoverflow, I'm still unable to get it to work even after a couple of days of trying. It's my first week with express and node and so I don't know if I'm doing the small things right. I basically want to upload a file and later on save it to the file system, however, I'm unable to proceed with req.files giving me undefined. Please see my code below.

This is my app.js

var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var routes = require('./routes/index');
var users = require('./routes/users');
var upload = require('./routes/upload.js');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', routes);
app.use('/users', users);
app.use('/upload', upload);

/// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err); 
});

/// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
        message: err.message,
        error: err
    });
});
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
    message: err.message,
    error: {}
});
});


module.exports = app;

This is my routes/upload.js

    var express = require('express');
    var router = express.Router();

    /* GET home page. */
    router.get('/', function(req, res) {
    console.log("");
    console.log(req.files);
    res.send('this is the page you get upon doing file upload');
    });

    module.exports = router;

This is my views/homepage.jade

doctype html
html
 head
  title= title
  link(rel='stylesheet', href='/stylesheets/style.css')
 body
  p select file to upload
  form(action="upload", method="get", enctype="multipart/form-data")
    input(type="file", name="displayImage")
    input(type="submit")

At the moment, I'm hearing a lot of terms like multer, connect-busboy, bodyParser being deprecated from express4 etc but with no real idea on how to proceed. Please advise me on how I can proceed and what code should be added.

Thanks.


Solution

  • A number of modules were removed from Express in 4.0 and are now separate packages you have to include. The easiest way to get started with it is to use express-generator to generate the scaffolding for you. This will include and require the correct packages for parsing cookies, and the request body. It doesn't include a file parser however. I put together an example using multer and put it on Github for you to reference.

    After you clone it, you can run npm install, and then npm start.

    One other thing you were doing incorrectly that I fixed was using app.get for your upload handler. You can't use GET to upload a file. In my example I changed this to a POST request. Here are the relevant snippets.

    app.js

    var express = require('express');
    var path = require('path');
    var favicon = require('serve-favicon');
    var logger = require('morgan');
    var cookieParser = require('cookie-parser');
    var bodyParser = require('body-parser');
    var multer = require('multer');
    
    var routes = require('./routes/index');
    var users = require('./routes/users');
    var upload = require('./routes/upload');
    
    var app = express();
    
    // view engine setup
    app.set('views', path.join(__dirname, 'views'));
    app.set('view engine', 'jade');
    app.use(multer({ dest: './uploads/'}))
    
    // uncomment after placing your favicon in /public
    //app.use(favicon(__dirname + '/public/favicon.ico'));
    app.use(logger('dev'));
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: false }));
    app.use(cookieParser());
    app.use(express.static(path.join(__dirname, 'public')));
    
    app.use('/', routes);
    app.use('/users', users);
    app.use('/upload', upload);
    
    // catch 404 and forward to error handler
    app.use(function(req, res, next) {
        var err = new Error('Not Found');
        err.status = 404;
        next(err);
    });
    
    // error handlers
    
    // development error handler
    // will print stacktrace
    if (app.get('env') === 'development') {
        app.use(function(err, req, res, next) {
            res.status(err.status || 500);
            res.render('error', {
                message: err.message,
                error: err
            });
        });
    }
    
    // production error handler
    // no stacktraces leaked to user
    app.use(function(err, req, res, next) {
        res.status(err.status || 500);
        res.render('error', {
            message: err.message,
            error: {}
        });
    });
    
    
    module.exports = app;
    

    index.jade

    extends layout
    
    block content
      h1= title
      p select file to upload
      form(action='upload', method='post', enctype='multipart/form-data')
        input(type='file', name='displayImage')
        input(type='submit')