File uploading with Express 4.0: req.files undefined
Asked Answered
E

14

289

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');
        });
    });
});
Ethelyn answered 16/4, 2014 at 15:54 Comment(5)
how does this work with multiple files?Doloroso
@Doloroso it should work just fine with multiple filesImaginable
ithink it is possible to do app.post('/fileupload',busboy(), function(req, res) {Edina
Good solution I just wanted to note that you have to create a ./files/ directory in your app's home directory otherwise you will get an error after you upload.Chios
How are temp files handled? Does busboy delete them automatically? I just don't see anywhere temp files being deleted before saving to disk.Kulak
I
238

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.

Imaginable answered 16/4, 2014 at 19:11 Comment(6)
Thanks, that worked. Although I had to use connect-busboy instead of just busboy. Updated my original post with the solution.Ethelyn
Thanks mate! I find connect-multiparty option best of these!Undulant
Is reformed still under development? Your last commit on github is from 2014...By the way, in your opinion, what's the best module to handle multipart form data? By "best" I mean the best supported and the one that works better (less bugs), with more features and with a longer future..I chose multer because it seemed the best supported, but I still think it should be more supported.Foreshank
[EDIT: it'ls ok, just saw the answer below.] did multipart with in express 3.0, and then broken in 4.0? i ask because this tutorial uses 3.4.8 and can upload files without the need for any extra middleware blog.robertonodi.me/simple-image-upload-with-expressTendency
@Tendency The github repo for that particular example you linked to actually has the dependencies checked into the repo. If you dig through those dependencies you will see Express 3.x is included, as well as Connect 2.x (which still had a multipart module bundled with it). That is why multipart handling was working "out of the box."Imaginable
Hello @mscde, Can you please see to this issue that I'm facing ? #74173960Gormley
A
61

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


});
Alltime answered 9/10, 2016 at 10:58 Comment(1)
too slow for large filesCeciliacecilio
P
24

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!!!');
});
Permanganate answered 23/10, 2018 at 21:9 Comment(0)
W
14

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' } }
Woolcott answered 23/4, 2016 at 20:0 Comment(0)
F
10

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!

Facultative answered 15/12, 2017 at 5:30 Comment(0)
B
5

Please use below code

var fileupload = require("express-fileupload");
app.use(fileUpload());
Began answered 23/10, 2018 at 9:46 Comment(1)
var fileupload = require("express-fileupload"); app.use(fileupload());Colt
S
5

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){

...

});
Schoolboy answered 6/7, 2020 at 7:51 Comment(2)
Took me more than a dozen timeouts to realize you forgot to call the middleware correctly.Verve
@veteri, true...Schoolboy
U
2

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());
Upkeep answered 6/7, 2021 at 9:15 Comment(0)
H
2

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

Highpriced answered 2/8, 2021 at 16:14 Comment(0)
S
1

You can use express-fileupload npm package to decode files like

const fileUpload = require('express-fileupload');
app.use(fileUpload({useTempFile: true}))

Note: I am using cloudinary to upload image

enter image description here

Sweatshop answered 27/1, 2023 at 16:26 Comment(0)
S
1

const fileUpload = require("express-fileupload");

router.route("/uploads").post(fileUpload(), uploadProductImage);

//Adding fileUpload() middleware in routes worked for me.

Skein answered 25/4, 2023 at 14:17 Comment(1)
Hi, there is already an answer with this suggestion. When answering an old question, be sure to add something useful and above all original. Thank you!Hoseahoseia
J
0

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');
Jasperjaspers answered 24/6, 2018 at 15:39 Comment(0)
A
0

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

Attenweiler answered 21/12, 2021 at 12:13 Comment(0)
R
-3

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.

Ralline answered 13/1, 2017 at 14:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.