简体   繁体   中英

Node.js, multer and req.body empty

Here it is my problem, I have a form where I can insert a file and a field but I receive only the file and not the parameter test ? Why?

This is my code:

app.js:

var express = require('express');
var bodyParser = require('body-parser');
var app = express();
var port = 8000;
var multer = require('multer'); // v1.0.5
var storage =   multer.diskStorage({
  destination: function (req, file, callback) {
    callback(null, './uploads');
  },
  filename: function (req, file, callback) {
    callback(null, file.originalname.substring(0,file.originalname.lastIndexOf('.')) + '-' + Date.now() + file.originalname.substring(file.originalname.lastIndexOf('.'),file.originalname.length));
  }
});
var upload = multer({ storage : storage}).single('fileUpload');

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));

app.post('/api/upload',function(req,res){
    console.log(req.body);
    upload(req,res,function(err) {
        if(err) {
            return res.end("Error uploading file.");
        }
        res.end("File is uploaded");
    });
});

app.listen(port, function () {
    console.log('Express server inizializzato sulla porta ' + port);
});

index.html:

<html>
    <head>
        <title>Test upload</title>
    </head>
    <body>
        <form name="form" action="http://localhost:8000/api/upload" method="post" enctype="multipart/form-data">
            <input type="text" name="test" />
            <input type="file" name="fileUpload" />
            <input type="submit" value="invia" />
        </form>
    </body>
</html>

Someone can help me?

2017 Update

From Readme

Note that req.body might not have been fully populated yet. It depends on the order that the client transmits fields and files to the server.

I resolved my issue by reversing the order of my form object properties in the front end:

    var newFormObj  = new FormData();
    newFormObj.append('internalUserID', internalUserID);
    newFormObj.append('listingImage', this.binaryImages[image]);

On the backend:

var storage = multer.diskStorage({
  destination: function (req, file, cb) {
    console.log(req.body.internalUserID) // YAY, IT'S POPULATED
    cb(null, 'listing-pics/')
  },                    
  filename: function (req, file, cb) {
    cb(null, file.fieldname + '-' + Date.now())
  }                     
});                     

var upload = multer({ storage: storage });

You need to re-arrange the fields from frontend request, Below i will explain,

I am using multer to upload multiple files and single file in my nodejs application.

Postman request screenshot ( Mistaked ): 在此处输入图片说明

Postman request screenshot ( correct method ): 在此处输入图片说明

See the difference in order of fields. Always attach media files in last of the req content.

I had spent a 2 hours nearly to find this. Definitly Work. Just try it.

I resolve moving req.body at the end of the post function:

app.post('/api/upload?:test',function(req,res){

    upload(req,res,function(err) {
        if(err) {
            return res.end("Error uploading file.");
        }
        res.end("File is uploaded");
    console.log(req.body);

    });
});

If someone can tell me why I will happy to learn a new thing! But, for now, I resolved!

Move your console.log(req.body) inside upload(req,res,function(err) {...})

The default express body-parser cannot work with multipart/form-data, hence we use multer to parse form-data which is accessible inside your upload function.

In case anyone else comes here with a slightly more complex initial layout like the below, moving the upload function into the file with each route and using them there seems to have solved this for me. Why it's this temperamental, I don't know and honestly it's been a giant headache.

It should be noted that I had a custom storage engine that streamed the file to disk which may have caused this issue however it only happened with 1 specific route which was functionally identical to several others which worked perfectly.

Hope this might help someone else one day.

Initial app layout

app.ts


import express from 'express';
import multer from 'multer';

import profilePicture from './routes/profile-picture.ts';

const upload = multer();

class Server {
    constructor() {
        this.app = express()
    }

    setRoutes() {
        this.app.use( '/upload', upload.single( 'profile' ), profilePicture );
    }

    // ... other methods
}

profile-picture.ts

import { Router } from 'express';

const profilePicture = Router();

profilePicture.post( '/', ( req, res, next ) => {
    console.log( req.body ); // This was always empty, regardless of field order
    // do something with req
}

Updated layout that works for some reason

app.ts

import express from 'express';

import profilePicture from './routes/profile-picture.ts';


class Server {
    constructor() {
        this.app = express()
    }

    setRoutes() {
        this.app.use( '/upload', profilePicture );
    }

    // ... other methods
}

profile-picture.ts

import { Router } from 'express';
import multer from 'multer';

const upload = multer();

const profilePicture = Router();

profilePicture.post( '/', upload.single( 'profile' ), ( req, res, next ) => {
    console.log( req.body ); // No longer empty, hooray!
    // do something with req
}

You can manually reorder the fields with javascript to make sure that fields are sent before files.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM