When working with streams, it's good practice to wait for streams to become ready before using them and handle the errors.
The following snippet waits for the ready
event on both streams before piping the ReadStream to the WriteStream and handles the errors.
// assuming you're using express and the app instance is bound to a variable named app
const fs = require('fs');
const path = require('path');
// ...
// helper function: returns a promise that gets resolved when the specified event is fired
const waitForEvent = (emitter, event) => new Promise((resolve, reject) => emitter.once(event, resolve));
app.post('/handle-post', async (req, res) => {
// TODO: validate the input
const { ExRequestId } = req.body;
const srcFileName = `${path.join(mainDir, ExRequestId)}.png`;
const destFileName = `${path.join(mainDir, docReq._id)}.png`;
const srcStream = fs.createReadStream(srcFileName);
await waitForEvent(srcStream, "ready");
const destStream = fs.createWriteStream(destFileName);
await waitForEvent(destStream, "ready");
const handleError = err => res.status(500).json(err);
srcStream.on("error", handleError);
destStream.on("error", handleError);
srcStream.pipe(destStream);
await waitForEvent(srcStream, 'end');
res.status(200).json({srcFileName, destFileName});
});
I also put together a minimal working example. It can be found here.