[Fixed] Upload image and read json with express js

Issue

Problem:
Trying to get json string but req.body in the post data handler returns undefined. Is it even possible to send json and file in one post request to the server?

Code:

Data sended to the server:

function saveFile(e) {
    let info = {titleI: title.value, dirI: dir.value};
    let xhr = new XMLHttpRequest();
    let formData = new FormData();
    let file = e;     

    formData.append("info", JSON.stringify(info));   
    formData.append("file", file);

    xhr.onreadystatechange = state => { console.log(xhr.status); }
    xhr.timeout = 5000;
    xhr.open("POST", '/register'); 
    xhr.send(formData);

}

The post data handler:

router.post("/", (req, res) => {

    console.log(req.body.info)

    var fstream;
    req.pipe(req.busboy);
    
    req.busboy.on('file', function (fieldname, file, filename) {

        let dirName = "a"
        
        fs.mkdir("D:/node website/ipgrabber/files/"+dirName+"/", function(err) {
            if (err) {
              console.log(err)
            }
        })

        fstream = fs.createWriteStream("D:/node website/ipgrabber/files/"+dirName+"/" + filename);
        file.pipe(fstream);

        fstream.on('close', function () {                
            res.redirect('back');
        });
    });
})  

This is the main class:

var express = require('express')
var http = require('http')

const mongoose = require('mongoose')
const { json } = require('express')
var cookieParser = require('cookie-parser')

var app = express()
var server = http.createServer(app)

const bodyParser = require('body-parser')
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: true}));

var busboy = require('connect-busboy');
app.use(busboy()); 

//error handler
mongoose.connect('mongodb://localhost:27017/grabber', {useNewUrlParser: true, useUnifiedTopology: true});

app.use(cookieParser())

app.set("view engine", "ejs")

app.set('views', __dirname+'/views/html/');

app.use("/js", express.static(__dirname + "/views/js"))
app.use("/css", express.static(__dirname + "/views/css"))

const registerRoute = require("./routes/register")
const grabberRoute = require("./routes/grabber")

app.use("/register", registerRoute)
app.use("/id", grabberRoute)

app.get("/", (req, res) => {
    
    res.redirect("/register")
})


app.use(function (err, req, res, next) {
    res.status(400).send("Error code: 2 <hr> This page is currently inaccessible! <br> <a href='/'>GO TO HOMEPAGE</a>")

    console.log(err)
})

server.listen(80)

Project resources:

body-parser – 1.19.0

connect-busboy – 0.0.2

cookie-parser – 1.4.5

crypto-js 4.0.0

ejs 3.1.5

express 4.17.1

mongoose 5.11.19

Solution

By default, express can’t manage to get multipart/form-data correctly.
You have to use a middleware to handle and parse this request.
I recommend to use multer.

In your case, you’re using connect-busboy so the info should be handled like this:

    req.busboy.on('field', function(key, value, keyTruncated, valueTruncated) {
        console.log('your info is here', key, value);
    });

Leave a Reply

(*) Required, Your email will not be published