1
app.post('/upload',upload.array('photos',30),function(req,res,next){
    for (var index in req.files)
        {    
        var file = req.files[index];
        var loc = file.destination;
        var output= uploadFolder+req.body.user+'/download/'+formatDate();
        };
    console.log('output: '+output);
    console.log('loc: '+loc);
    var cmd = 'python demo.py -i '+loc+' -o '+output+' --isDlib True'; //cmd demo.py 
    // res.write('File Processing..');

    child_process.exec(cmd,function(err,stdout,stderr){            
        var fileLocation = output+'.zip';
        console.log(fileLocation);

        zipFolder(output,fileLocation, function(err) {

            if(err) {
                console.log('oh no!', err);
            } else {

                console.log('EXCELLENT');
                res.download(fileLocation,'Files');                    
                // res.redirect('/form');                  
            }
        });                 
   }); 
});

Hi everyone, I've just started out with Node and I tried to build a simple server to let user upload their image. The image will then be changed to 3D by python.

Now I want to display a message when the user is waiting for the file transfer to complete.

I tried to send the message by response.write before the child_process ,and in the end I wish to redirect the website by route.

But I always get the error (The codes which I comment out. ): Can't set headers after they are sent.

Can someone help me to fix it? Thanks a lot.

Neil Su
  • 345
  • 1
  • 3
  • 7

2 Answers2

3

As Sashi said correctly, you can't respond twice from your API

Try:

someUploadRoute.js:

...
..
console.log(fileLocation);
zipFolder(output,fileLocation, function(err) {
  if (err) {
    myMessage="error encountered on upload"
    console.log(myMessage, err);
    res.json({success:false, error:err});
  }
  else {
    myMessage = "upload successful";
    console.log(myMessage);
    res.download(fileLocation, 'Files');
  }
)}

Edit to display message to frontend:

When your someUploadComponent.ts calls your someUploadService.service.ts you could check for the returned values. Partially pseudo code follows:

someUploadComponent.ts:

   this.someUploadService.upload(args).subscribe(uploadResponse => {
     if (uploadResponse.success == false) { // will be undefined if no err
       display err message in dialog or whateva
     }
     else {
       do whatever..
     }

someUploadService.service.ts:

upload(args) {
   return this.http.post('http://somehost:3000/fileOps/upload',user).pipe(map(res => res.json()));
}
iLuvLogix
  • 5,920
  • 3
  • 26
  • 43
  • Hello, thanks for your answer. But I want to show the message on client,not on terminal. It's that possible I sent some message in just one response? – Neil Su Oct 11 '18 at 08:48
  • check for the returned json for success.false in your component and display a dialog, snackbar, div (set visibility) or whatever.. – iLuvLogix Oct 11 '18 at 09:17
2

The problem with your code is that once you call res.send your API's response will be returned (on line 74).

Hence you get the error Can't set headers after they are sent because the res object has already been returned by node.

Calling res.redirect on line 88 has the same effect as well.

You cannot send a response back when the file is being uploaded. Sending a response will finish your API call. And you will have to make a separate call to check the status of your upload. I would recommend showing a response that your file is being uploaded, from the frontend instead of the API.

This stackoverflow question would be helpful in getting a better understanding of how res works!

Sashi
  • 2,659
  • 5
  • 26
  • 38
  • I got it. Thanks for your answer. But if I wanna show some message on client , just in one response. It's that possible ? Like use 'next()' to make process? – Neil Su Oct 11 '18 at 08:44
  • If I understood your question correctly, next() is usually used with middleware. So I dont think you can use that to display messages on the client. – Sashi Oct 11 '18 at 08:47
  • Instead, you could get your frontend web or mobile application to display a message while waiting for the API to respond. – Sashi Oct 11 '18 at 08:47