1

I am trying to send a JSON array containing multiple files and input fields using axios. Processing the files and subsequent field and finally trying to send an object like :

[
  {file : "",
   text : ""
  }, {...}, {...}
]

ServerA.js

const bodyParser = require('body-parser');
const multer  = require('multer');
const upload = multer();

app.use(bodyParser.json()); 
app.use(upload.any());

app.post('/requestFile',(req,res) => {
let files = req.files;
let textInfo = req.body;
let form = [];
files.forEach((file,index)=>{
    let formObj = {};
    formObj.file = file;
    let key = Object.keys(textInfo)[index];
    let value = texInfo[key];
    formObj.text = value;
    form.push(formObj)
})
axios.request({
    method: 'post',
    url: `http://localhost:1001/receiveFiles`,
    headers: {
        'Content-Type': 'multipart/form-data'
    },
    data: {
        form
    }
}).then(response => {
    res.send('No Err');
}).catch(err=>{
    res.send('ERR')
})
})

But I'm getting an empty object when I try to print the body at the receiving end :

ServerB.js

app.use(bodyParser.json()); 
app.use(upload.any());

app.post('/receiveFiles', (req,res) => {
console.log("Print: " + JSON.stringify(req.body));
res.send('successful');
})

I'm getting the following result :

Print : {}

I'm new to Nodejs, it will be really great if someone can help me out

geepUser
  • 11
  • 3
  • As you make the call to `receiveFiles` from another endpoint, you cannot tell which part of your code has a bug. Try to call your `receivesFiles` with something like curl, postman, etc – farvilain Jun 16 '21 at 15:16

2 Answers2

0

Here is a code you can adapt to your need. As I told you in comment, calling a endpoint with a file that call another endpoint... that's not easy to debug.

Just put all this code (server + client) into a same file called app.js and run node app.js after installing needed package (do not install fs it is a node built-in)

Server part

const app = express();
const multer  = require('multer');
const upload = multer();

app.use(upload.any());

app.post('/receiveFiles', (req,res) => {
    console.log("Receiving:", JSON.stringify(req.body) );
    console.log("Files are:", req.files);
    res.send('successful');
});

app.listen(3000, () => {
    console.log("Started");

    tryIt();
});

The client part

const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');

const formData = new FormData();
formData.append('id', 1343);
formData.append('this file', fs.createReadStream('./app.js'));

function tryIt() {
    console.log("Calling the endpoint");

    const fullReq = {
        method: 'post',
        url: `http://localhost:3000/receiveFiles`,
        headers: formData.getHeaders(),
        data: formData
    };

    console.log('Req to be sent', fullReq);
    axios.request(fullReq).then(response => {
        console.log("data", response.data);
        console.log("status", response.status, response.statusText);
    }).catch(err=>{
        console.error(err);
    })
}

Expected results

Calling the endpoint
Req to be sent {
  method: 'post',
  url: 'http://localhost:3000/receiveFiles',
  headers: {
    'content-type': 'multipart/form-data; boundary=--------------------------224414152569192710241525'
  },
  data: FormData {
    _overheadLength: 266,
    _valueLength: 4,
    _valuesToMeasure: [ [ReadStream] ],
    writable: false,
    readable: true,
    dataSize: 0,
    maxDataSize: 2097152,
    pauseStreams: true,
    _released: false,
    _streams: [
      '----------------------------224414152569192710241525\r\n' +
        'Content-Disposition: form-data; name="id"\r\n' +
        '\r\n',
      '1343',
      [Function: bound ],
      '----------------------------224414152569192710241525\r\n' +
        'Content-Disposition: form-data; name="this file"; filename="app.js"\r\n' +
        'Content-Type: application/javascript\r\n' +
        '\r\n',
      [DelayedStream],
      [Function: bound ]
    ],
    _currentStream: null,
    _insideLoop: false,
    _pendingNext: false,
    _boundary: '--------------------------224414152569192710241525'
  }
}
Receiving: {"id":"1343"}
Files are: [
  {
    fieldname: 'this file',
    originalname: 'app.js',
    encoding: '7bit',
    mimetype: 'application/javascript',
    buffer: <Buffer 63 6f 6e 73 74 20 65 78 70 72 65 73 73 20 3d 20 72 65 71 75 69 72 65 28 27 65 78 70 72 65 73 73 27 29 3b 0a 63 6f 6e 73 74 20 61 70 70 20 3d 20 65 78 ... 1066 more bytes>,
    size: 1116
  }
]
data successful
status 200 OK
farvilain
  • 2,552
  • 2
  • 13
  • 24
0

To send a file with axios in Node.js you need to:

  1. Create a form using form-data library
  2. Set the request headers from the form with getHeaders()

Change your code to this:

const FormData = require('form-data');

// ...

app.post('/requestFile', (req, res) => {
  const files = req.files;
  const textInfo = req.body;
  
  // Construct form and append files and other data to it
  const form = new FormData();
  files.forEach((file, index) => {
    form.append('file', file, file.originalname);

    const key = Object.keys(textInfo)[index];
    form.append('text', textInfo[key]);
  });

  // Send form with axios and pass form boundary to the request header
  axios.post('http://localhost:1001/receiveFiles', form, {
    headers: {
      ...form.getHeaders(),
    },
  })
  .then(() => { ... });
});

Then on the receiving end:

app.post('/receiveFiles', upload.array('file'), (req, res) => {
  const files = req.files; // [{ file1 }, { file2 }, ...]
  const data = req.body; // { text: ['textInfoFile1', 'textInfoFile2', ....] 
});

For an in-depth explanation have a look at this article Send a File With Axios in Node.js. It covers a few common pitfalls and you'll learn how to send files that are stored as a Buffer or coming from a Stream.

Maxim Orlov
  • 1,942
  • 15
  • 18