简体   繁体   中英

Express.js Response Sent Callback

I have the following code in Node/Express that sends a file as a response then deletes the file using a timeout.

res.sendFile(req.params.id, { root: process.env.UPLOADPATH });

setTimeout(function () {
    if (fs.existsSync(process.env.UPLOADPATH + req.params.id)) { // check to ensure file still exists on file system
        fs.unlink(process.env.UPLOADPATH + req.params.id); // delete file from server file system after 60 seconds
    }
}, 60000);

If I didn't use the setTimeout it failed with an error. I'm assuming Express does the sendFile async so it was deleting the file before it actually sent.

Is there a better way to do this tho? Is there a way to check for when the file has been sent so I can safely delete it? Maybe like a sendFile callback or something?

Is there a better way to do this tho? Is there a way to check for when the file has been sent so I can safely delete it? Maybe like a sendFile callback or something?

Yes, you should just remove the file when the res.sendFile() is actually done. You can use the completion callback on res.sendFile() to know when it's done.

Also, it is an anti-pattern to use if (fs.existsSync(...)) and then delete the file because it can be subject to race conditions. If you want the file deleted, just delete it and handle any errors you might get:

  let filename = path.join(process.env.UPLOADPATH, req.params.id);
  res.sendFile(filename, function (err) {
    if (err) {
      next(err);
    } else {
      try {
        fs.unlink(filename); 
      } catch(e) {
        console.log("error removing ", filename); 
      }
    }
  });

I'm assuming Express does the sendFile async so it was deleting the file before it actually sent.

Yes, that is true.


You could also use the res.on('finish', ...) event to know when the sending of the response is done.

  let filename = path.join(process.env.UPLOADPATH, req.params.id);
  res.sendFile(filename);
  res.on('finish', function() {
      try {
        fs.unlink(filename); 
      } catch(e) {
        console.log("error removing ", filename); 
      }
  });

The method invokes the callback function fn(err) when the transfer is complete or when an error occurs. If the callback function is specified and an error occurs, the callback function must explicitly handle the response process either by ending the request-response cycle

  res.sendFile(fileName, { root: process.env.UPLOADPATH }, function (err) {
    if (err) {
      next(err);
    } else {
      // File has been sent
      console.log('Sent:', fileName);

       if (fs.existsSync(process.env.UPLOADPATH + req.params.id)) { 
          // check to ensure file still exists on file system
          fs.unlink(process.env.UPLOADPATH + req.params.id); 
          // delete file from server file system after 60 seconds
       }
    }
  });

The main drawback to res.on('finish', ...) is that it isn't called on the response being closed or on an error. Using on-finished will run the callback on closes, finishes, or errors. This is especially helpful in the case of deleting a file where you want to delete the file even on errors or situations like that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM