Search code examples
node.jsangularmulterform-data

Angular NodeJS Upload File and parameters together


I have been looking through multiple tutorials and stack overflow questions but for some reason I just cannot make this work. I have issues with uploading a file, so maybe fixing that first would solve the whole issue.

I tried a few options of sending a file from the front end to the back end, but it seems to always "get lost" before reaching the back end.

I have decided to use multer at the NodeJS backend to upload the file. Not sure if I am calling multer upload single right or not. Currently this is the code which I have for it:

  const multer = require('multer');
  const storage = multer.diskStorage({
    destination: './uploadedImages',
    filename: function(req,file,cb){
      cb(null,file.originalname)
    }
  }) ;

  const upload = multer({storage: storage})

  exports.saveDrawing = async(req, res, next) => {
    try
    {     
      //save image
      //tried a few different logs, but with FormData it seems like everything always empty
      console.log("Image:");
      console.log(req.body.drawingElement);
      console.log(req.file);
      
      upload.single('body.file');
      return res.status(200).json({message: element});
      }
    }
    catch (err)
    {
      console.log("Error at drawing save: " + err)
      return res.status(500).json({message: "Error - Could not add/edit Drawing"});
    }
  }

And this is how it is sent from the Angular front end:

    setDrawing(params, image): Observable<any> {
      const formData = new FormData();
      
      formData.append('file', image)
      formData.append('data', params)
      
      console.log("File: ");
      console.log(formData.get('file'));
      console.log("Data: ");
      console.log(formData.get('data'));
      
      return this.http.post<any>(`api/v1/structure/drawing/save`, formData);
    }

At this stage printing out the data shows the right values. And the browser shows the right payload too: enter image description here

At the back end I cannot see them in the req, req.body is empty, there is no req.form. For this api call before I have tried to include any files without the FromData I have accessed the data from req.body.

Am I looking for the data at the right place?


Solution

  • You're not using multer correctly, it's not doing anything.

    To implement it as a middleware which you call from your handler, check the example from the docs

    So, your handler should look something like this:

    // setup multer middleware, set file field name
    const upload = multer({storage: storage}).single('file');
        
    exports.saveDrawing = async(req, res, next) => {    
    
      // now use the middleware, handle errors
      upload(req, res, function (err) {
    
        if (err instanceof multer.MulterError) {
    
          // A Multer error occurred when uploading.
          return res.status(500).json({message: "Error - Could not add/edit Drawing"});
    
        } else if (err) {
          
          // An unknown error occurred when uploading.
          return res.status(500).json({message: "Error - Could not add/edit Drawing"});
        }
    
        // Everything went fine.
    
        console.log("Image:");
        console.log(req.body.drawingElement);
        console.log(req.file);
    
        return res.status(200).json({message: element});
    
      });
    });