Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

POSTing from Angular to Node. Getting empty body on node

Im posting two fields in Angular to a NodeJs endpoint.

I usually post on the body and everything is perfect at Node, but this time, I have to post a form to upload a file.

So this is my code for posting the form data (Angular side):

var APIURL = sessionStorage.getItem('endPoint') + "profile/updateeocoverage"; 
let formData = new FormData();
formData.append("data", JSON.stringify(this.payLoad));
if (this.eofile) {
  formData.append("myfile", this.eofile, this.eofile.name);
}
this.httpClient.post(APIURL,  formData).subscribe(
  result => {
  ....

My problem is that I always retrieved the body at node as follows:

router.post('/updateeocoverage', async   (req, res, next) => {
    console.log(req.body)
    return;
    ....

But with the method Im using now in Angular, req.body is retrieving {}

Is the POST wrong, or the router wrong at Node side?

Thanks.

UPDATE ON PABLO'S ANSWER BELOW (SOLUTION PROVIDED) for whoever runs into this issue:

Using Multer solved the problem, but as he said some workaround is needed as to set the file name, but most important it is required to authenticate the user, so:

const multer = require('multer')
const path = require('path')

To authenticate the user, I send the authentication parameters on the header. Sending it as formdata.append didn't work for me. This sets true or false to upload the file, otherwise anyone can upload anything to the route:

async function authenticateUser(req, file, cb) {
    let tempcred = JSON.parse(req.headers.data)
    let credentials = tempcred.credentials;
    let userData = await utils.isValidUser((credentials), false);
    if (userData.isValid == false) {
        cb(null, false)
        return;
    }
    else {
        cb(null, true)
    }
}

Then, since Multer uploads the file with a random name, and I need to save it with the user ID name and the file extension, I do the following:

var storage = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, 'uploads/eofiles/')
    },
    filename: async function (req, file, cb) {
        let tempcred = JSON.parse(req.headers.data)
        let credentials = tempcred.credentials;
        let userid = await utils.decrypt(credentials.userid, process.env.SECRET);
        cb(null, userid + path.extname(file.originalname))
    }
});

Finally, I declare the upload variable for using it with Multer:

var upload = multer({ storage: storage, fileFilter: authenticateUser })

And set the router:

router.post('/updateeofile', upload.single("myfile"), async (req, res, next) => {
let filename = req.file.filename //gets the file name
...
...
do my stuff, save on database, etc
...
...
});

For the record, "myfile" is the input file id.

And this is how I upload the file from Angular:

var APIURL = sessionStorage.getItem('endPoint') + "eoset/updateeofile";    
    const httpOptions = {
      headers: new HttpHeaders({
        'data': `${JSON.stringify(this.payLoad)}`
      })
 };
 let formData = new FormData();
    if (this.eofile) {
      formData.append("myfile", this.eofile, this.eofile.name);
    }
    this.httpClient.post(APIURL, formData, httpOptions).subscribe(
      result => {
...
...
...
 },
      error => {

});

I spent 6 hours on this today. I hope this helps you and saves you some time.

like image 607
Danielle Avatar asked Jan 21 '26 07:01

Danielle


1 Answers

Try using Multer

npm i multer

const multer  = require('multer')
const upload = multer({ dest: 'uploads/' })
router.post('/updateeocoverage', upload.single('myfile'), function (req, res, next) {
    res.json(JSON.parse(req.body.data))
  })

You will need to indicate the destination folder (line 2) and work out the file name, extension, etc.

like image 113
Pablo Varela Avatar answered Jan 23 '26 01:01

Pablo Varela



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!