1

I am creating a rest API server in Express.js. The goal of this of my particular issue is creating a post route that takes multipart/form-data request and sends file/text/field to an external API. At the moment I am running into an issue even trying to test it with postman.

I can send a response with the parsed data from multer, but when I try to create a new form-data I cannot access the request body, TypeError: Cannot read property 'name' of null

What am I doing wrong? Is there a better way? Open to suggestions.

My server code is as follows:

const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const request = require("request");
const multer = require("multer");
const upload = multer({ dest: 'uploads/'});
const FormData = require("form-data");
const fs = require("fs");

const app = express();
const port = 3000;

app.use(cors());

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

///.....

app.post('/jobs/:id', upload.single('resume'), (req, res) => {

    let url = '...';

    var header = req.headers['content-type']

    var tmp_path = req.file.path;
    var tar_path = 'uploads/' + req.file.originalname;
    var src = fs.createReadStream(tmp_path);
    var dest = fs.createWriteStream(tar_path);
    src.pipe(dest);

    var data = new FormData();
    data.append('name', req.body.name)
    data.append('phone', req.body.phone)
    data.append('email', req.body.email)
    data.append('resume', fs.createReadStream(tar_path))
    
    const options = {
        url: url,
        method: 'POST',
        headers:{
            'Content-Type': header
        },
        formData: data
    }

    request(options, (err, rez, body) => {
        if (err){
            console.log("There was an error: " + err)
        }
    }).pipe(res)  

    res.send(res)
})


app.listen(port, () => console.log(`Server is listening on port ${port}`));

EDIT

This is the request I am trying to make:

curl -F name="test" -F phone="0000000000" -F email="[email protected]" -F resume=@"Desktop/test.txt" http://cfr.thewb.co/jobs/408189/
7
  • Can you add the actual request you're trying to do? Maybe as a curl? Commented Jul 31, 2020 at 16:08
  • @eol I edited the initial post with the request Commented Jul 31, 2020 at 16:32
  • I would guess that the issue comes from mixing body-parser and multer at the same time, but I haven't tested it. Does it work if you remove body parser? Multer should return the text-based form data. Commented Jul 31, 2020 at 16:50
  • @glmdev Doesn't seem to make a difference. Commented Jul 31, 2020 at 16:59
  • Try replacing "upload.single('...')" with "upload.any()". I believe multer is only doing the file field, not the text fields, when you set single. Commented Jul 31, 2020 at 17:09

1 Answer 1

0

So, after much digging and playing around I was finally able to figure it out. There are couple of things that I needed to fix.

  • Still not sure as to why it didnt work, but I removed the new FormData() function altogether and turned it into an Object.
  • I had to remove .pipe() call as it was giving me a circular structure error.
  • and lastly in my options I need quotes around "formData" for my request.

Here is the cleaned up code:

app.post('/jobs/:id', upload.single('resume'), (req, res, next) => {

    let url = '...';

    var header = req.headers['content-type'];

    function newObj(name,phone,email,resume){
        return{
            name: name,
            phone: phone,
            email: email,
            resume: {
                value: resume.buffer,
                options: resume.originalname
            }
        }
    }
    
    const options = {
        url: url,
        method: 'POST',
        headers:{
            'Content-Type': header
        },
        "formData": newObj(req.body.name,req.body.phone,req.body.email,req.file),
        'auth': {
            'username': PASS,
            'password': KEY,
        }
    }

    request(options, (err, rez, body) => {
        if (err){
            res.send(err)
        }
        if(rez){
            res.send(rez)
        }
    })
    
})
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.