File uploading with Express 4.0: req.files undefined

node.jsExpress

node.js Problem Overview


I'm attempting to get a simple file upload mechanism working with Express 4.0 but I keep getting undefined for req.files in the app.post body. Here is the relevant code:

var bodyParser = require('body-parser');
var methodOverride = require('method-override');
//...
app.use(bodyParser({ uploadDir: path.join(__dirname, 'files'), keepExtensions: true })); 
app.use(methodOverride()); 
//...
app.post('/fileupload', function (req, res) {
  console.log(req.files); 
  res.send('ok'); 
}); 

.. and the accompanying Pug code:

form(name="uploader", action="/fileupload", method="post", enctype="multipart/form-data")
	input(type="file", name="file", id="file")
	input(type="submit", value="Upload")

Solution
Thanks to the response by mscdex below, I've switched to using busboy instead of bodyParser:

var fs = require('fs');
var busboy = require('connect-busboy');
//...
app.use(busboy()); 
//...
app.post('/fileupload', function(req, res) {
	var fstream;
    req.pipe(req.busboy);
    req.busboy.on('file', function (fieldname, file, filename) {
    	console.log("Uploading: " + filename); 
        fstream = fs.createWriteStream(__dirname + '/files/' + filename);
        file.pipe(fstream);
        fstream.on('close', function () {
            res.redirect('back');
        });
    });
});

node.js Solutions


Solution 1 - node.js

The body-parser module only handles JSON and urlencoded form submissions, not multipart (which would be the case if you're uploading files).

For multipart, you'd need to use something like connect-busboy or multer or connect-multiparty (multiparty/formidable is what was originally used in the express bodyParser middleware). Also FWIW, I'm working on an even higher level layer on top of busboy called reformed. It comes with an Express middleware and can also be used separately.

Solution 2 - node.js

Here is what i found googling around:

var fileupload = require("express-fileupload");
app.use(fileupload());

Which is pretty simple mechanism for uploads

app.post("/upload", function(req, res)
{
	var file;

	if(!req.files)
	{
		res.send("File was not found");
		return;
	}

	file = req.files.FormFieldName;  // here is the field name of the form

	res.send("File Uploaded");
	
	
});

Solution 3 - node.js

  1. Make sure that your file is really sent from the client side. For example you can check it in Chrome Console: screenshot

  2. Here is the basic example of NodeJS backend:

    const express = require('express'); const fileUpload = require('express-fileupload'); const app = express();

    app.use(fileUpload()); // Don't forget this line!

    app.post('/upload', function(req, res) { console.log(req.files); res.send('UPLOADED!!!'); });

Solution 4 - node.js

It looks like body-parser did support uploading files in Express 3, but support was dropped for Express 4 when it no longer included Connect as a dependency

After looking through some of the modules in mscdex's answer, I found that express-busboy was a far better alternative and the closest thing to a drop-in replacement. The only differences I noticed were in the properties of the uploaded file.

console.log(req.files) using body-parser (Express 3) output an object that looked like this:

{ file: 
   { fieldName: 'file',
     originalFilename: '360px-Cute_Monkey_cropped.jpg',
     name: '360px-Cute_Monkey_cropped.jpg'
     path: 'uploads/6323-16v7rc.jpg',
     type: 'image/jpeg',
     headers: 
      { 'content-disposition': 'form-data; name="file"; filename="360px-Cute_Monkey_cropped.jpg"',
        'content-type': 'image/jpeg' },
     ws: 
      WriteStream { /* ... */ },
     size: 48614 } }

compared to console.log(req.files) using express-busboy (Express 4):

{ file: 
   { field: 'file',
     filename: '360px-Cute_Monkey_cropped.jpg',
     file: 'uploads/9749a8b6-f9cc-40a9-86f1-337a46e16e44/file/360px-Cute_Monkey_cropped.jpg',
     mimetype: 'image/jpeg',
     encoding: '7bit',
     truncated: false
     uuid: '9749a8b6-f9cc-40a9-86f1-337a46e16e44' } }

Solution 5 - node.js

multer is a middleware which handles “multipart/form-data” and magically & makes the uploaded files and form data available to us in request as request.files and request.body.

installing multer :- npm install multer --save

in .html file:-

<form method="post" enctype="multipart/form-data" action="/upload">
    <input type="hidden" name="msgtype" value="2"/>
    <input type="file" name="avatar" />
    <input type="submit" value="Upload" />
</form>

in .js file:-

var express = require('express');
var multer = require('multer');
var app = express();
var server = require('http').createServer(app);
var port = process.env.PORT || 3000;
var upload = multer({ dest: 'uploads/' });

app.use(function (req, res, next) {
  console.log(req.files); // JSON Object
  next();
});

server.listen(port, function () {
  console.log('Server successfully running at:-', port);
});

app.get('/', function(req, res) {
  res.sendFile(__dirname + '/public/file-upload.html');
})

app.post('/upload', upload.single('avatar'),  function(req, res) {
  console.log(req.files); // JSON Object
});

Hope this helps!

Solution 6 - node.js

Please use below code

app.use(fileUpload());

Solution 7 - node.js

Just to add to answers above, you can streamline the use of express-fileupload to just a single route that needs it, instead of adding it to the every route.

let fileupload = require("express-fileupload");

...

//Make sure to call fileUpload to get the true handler
app.post("/upload", fileupload(), function(req, res){

...

});

Solution 8 - node.js

A package installation needs for this functionality, There are many of them but I personally prefer "express-fileupload". just install this by "npm i express-fileupload" command in the terminal and then use this in your root file

const fileUpload = require("express-fileupload");
app.use(fileUpload());

Solution 9 - node.js

PROBLEM SOLVED !!!!!!!

Turns out the storage function DID NOT run even once. because i had to include app.use(upload) as upload = multer({storage}).single('file');

 let storage = multer.diskStorage({
        destination: function (req, file, cb) {
            cb(null, './storage')
          },
          filename: function (req, file, cb) {
            console.log(file) // this didn't print anything out so i assumed it was never excuted
            cb(null, file.fieldname + '-' + Date.now())
          }
    });
    
    const upload = multer({storage}).single('file');

Solution 10 - node.js

I added multer as global middleware before methodOverride middleware, and it worked in router.put as well.

const upload = multer({
    storage: storage
}).single('featuredImage');
app.use(upload);

app.use(methodOverride(function (req, res) {
  ...
}));

Solution 11 - node.js

With Formidable :

const formidable = require('formidable');

app.post('/api/upload', (req, res, next) => {
  const form = formidable({ multiples: true });

  form.parse(req, (err, fields, files) => {
    if (err) {
      next(err);
      return;
    }
    res.json({ fields, files });
  });
});

https://www.npmjs.com/package/formidable

Solution 12 - node.js

express-fileupload looks like the only middleware that still works these days.

With the same example, multer and connect-multiparty gives an undefined value of req.file or req.files, but express-fileupload works.

And there are a lot of questions and issues raised about the empty value of req.file/req.files.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionsafwancView Question on Stackoverflow
Solution 1 - node.jsmscdexView Answer on Stackoverflow
Solution 2 - node.jsAnton StafeyevView Answer on Stackoverflow
Solution 3 - node.jsDzmitry KulahinView Answer on Stackoverflow
Solution 4 - node.jsHPierceView Answer on Stackoverflow
Solution 5 - node.jsParth RavalView Answer on Stackoverflow
Solution 6 - node.jsGaurav kumarView Answer on Stackoverflow
Solution 7 - node.jswokoro douye samuelView Answer on Stackoverflow
Solution 8 - node.jsMahmudul MuradView Answer on Stackoverflow
Solution 9 - node.jsANUBISView Answer on Stackoverflow
Solution 10 - node.jsavrahammView Answer on Stackoverflow
Solution 11 - node.jsZahir MasoodiView Answer on Stackoverflow
Solution 12 - node.jstrdView Answer on Stackoverflow