0

Trying to upload a file from Angularjs UI to nodejs server but facing issues with bodyparser, adding limit to it throws -

"SyntaxError: Unexpected token - in JSON at position 0",

if limit not added throws -

"Payload too large"

I am using connect-multiparty middleware to upload the file. Tried with {limit: '50mb'} in bodyparser and without any limit as well.

UI Code -

$('#imgupload').on('change', function  (evt) {
   let uploadedFiles = evt.target.files;
   let formData = new FormData();
    for (var i = 0; i < uploadedFiles.length; i++) {
        formData.append("uploads[]", uploadedFiles[i], 
        uploadedFiles[i].name);
    }
   let url =   "/upload";
   httpService.restApi(url,formData)
       .then(function (response) {
           console.log("the file has been uploaded to local server 
           ",response);
   });
});

Nodejs (server code)-

const  multipart  =  require('connect-multiparty');  
const  multipartMiddleware  =  multipart({ uploadDir:  './uploads' });

app.use(bodyParser.json({limit: '50mb'}));

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

app.post('/upload', multipartMiddleware, (req, res) => {  
    res.json({
        'message': 'File uploaded succesfully.'
    });
});
3
  • When you say "it" throws, what do you mean by "it"? Commented May 16, 2019 at 13:11
  • bodyParser.json({limit: '50mb'}) Commented May 16, 2019 at 14:45
  • The $http service will automatically set the correct Content-Type header if you use it correctly. See How to POST FormData Using the $http Service. Commented May 17, 2019 at 13:21

2 Answers 2

0

Remove the bodyParser middleware from the path:

const  multipart  =  require('connect-multiparty');  
const  multipartMiddleware  =  multipart({ uploadDir:  './uploads' });

̶a̶p̶p̶.̶u̶s̶e̶(̶b̶o̶d̶y̶P̶a̶r̶s̶e̶r̶.̶j̶s̶o̶n̶(̶{̶l̶i̶m̶i̶t̶:̶ ̶'̶5̶0̶m̶b̶'̶}̶)̶)̶;̶

̶a̶p̶p̶.̶u̶s̶e̶(̶b̶o̶d̶y̶P̶a̶r̶s̶e̶r̶.̶u̶r̶l̶e̶n̶c̶o̶d̶e̶d̶(̶{̶e̶x̶t̶e̶n̶d̶e̶d̶:̶ ̶t̶r̶u̶e̶}̶)̶)̶;̶

app.post('/upload', multipartMiddleware, (req, res) => {  
    res.json({
        'message': 'File uploaded succesfully.'
    });
});

The contents is application/form-data, not application/json or application/x-www-form-urlencoded.

Sign up to request clarification or add additional context in comments.

2 Comments

I can't remove bodyParser as all other APIs in my backend are using bodyParser. But i found a solution. Will be posting my solution soon. I used "multer" library instead of "connect-multiparty" and while calling my nodejs API "/upload" i used fetch instead of $http or httpService as fetch automatically assigns the correct Content-Type header (which in this case is multipart/form-data)
The $http service will automatically set the correct Content-Type header if you use it correctly. See How to POST FormData Using the $http Service.
0

If you use multer and make the API call using $http explicitly setting the "Content-Type" header to multipart/form-data you will get "Multer: Boundary not found error" and if you remove the "Content-Type" header or set it to false it throws - "Converting circular structure to JSON error". Hence i used "fetch" to make the API call as it automatically identified the "Content-Type".

UI Code (modified as below) -

$('#imgupload').unbind('change').on('change', function  (evt) {
    evt.stopPropagation();
    evt.preventDefault();
   let uploadedFiles = evt.target.files;


   let formData = new FormData();
   for(let i=0; i<uploadedFiles.length;i++){
    formData.append("uploads", uploadedFiles[i], uploadedFiles[i].name);
   }

   let url = '/upload';
   var req = {
    method: 'POST',
    body: formData
   }

   fetch(url,req).then(function(response) {
        console.log("the file has been uploaded to local server ",response);
        $scope.uploadToSftp();
   });

});

Nodejs Code (modified as below) -

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

app.use(bodyParser.json({limit: '50mb'}));
app.use(bodyParser.urlencoded({  
  extended: true
}));

app.post('/upload', multipartMiddleware.array("uploads",2), function(req, res) 
{
  console.log("the upload api is called");
  return res.send(req.files);
});

2 Comments

The $http service will automatically set the correct Content-Type header if you use it correctly. See How to POST FormData Using the $http Service.
Keep in mind that the ES6 promises returned from the fetch API are not integrated with the AngularJS framework. Only operations which are applied in the AngularJS execution context will benefit from AngularJS data-binding, exception handling, property watching, etc.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.