Search code examples
javascriptnode.jsexpressstreamnode-streams

Node.js Stream :- Streams functions are not invoking for second time for same file


SFTB, i have a POST request coming to my server with multipart/form-data, now from that request i want to get contents of file.

I am reading the file supplied through streams and the piping that to cvsParser which is just an instance of csv-streamify after doing that we are passing the content to custom Transform function that fetch's the resource using http[ I am using got for that] and after fetching it i am compressing the image.

Now issue is, when i submit the file for first time it works like charm but, when i am trying to submit same file second time it skips the whole stream part and directly jumps to finish event handler.

Logs for first time :-

Submitting
Converting image at C:\image-minifier-sqd\build\src\1469004088476.bell.svg
Build is present at build\dest\1469004088476.bell.svg
Converting image at C:\image-minifier-sqd\build\src\1469004088996.mail.svg
Build is present at build\dest\1469004088996.mail.svg
Finished

Logs when i submit same file second time[Both with and without refresh on front-end]

Submitting
Finished

FYI, on front-end i am using fetch API to make POST request.

My Server code :-

function createParser() {
  var parser = new Transform({objectMode: true});
  parser._transform = function(data, encoding, done) {
    const date = new Date();
    const link = data.toString().slice(2,-3);
    const fileName = date.getTime()+ '.' +link.split( '/' ).pop(),
          filePath = path.resolve(__dirname,`build/src/${fileName}`);
    got.stream(link)
    .pipe(fs.createWriteStream(filePath,{flags:'a'}))
    .on('close',_ => {
      console.log(`Converting image at ${filePath}`)
      //Compressing images
      imagemin([filePath],'build/dest',{
        plugins: [
          imageminMozjpeg(),
          imageminPngquant({speed: 10}),
          imageminSvgo(),
          imageminGifsicle()
        ]
      })
      .then(file => {
        console.log(`Build is present at ${file[0].path}`);
        this.push(file[0].path);
        done(); 
      }); 
    });  
  };

  return parser;
}
//A request comes here with multipart/form-data
app.post('/submit/csv',upload.array('data'),(req, res) => {
  console.log('Submitting')
  const stream = fs.createReadStream(path.resolve(__dirname,req.files[0].path))
                  .pipe(csvParser)
                  .pipe(createParser())
                  .pipe(res)
                  .on('finish',_ => {
                    log('Finished');
                    res.end();
                  });

});

Thanks.


Solution

  • I think the problem is related with the reuse of the csvParser. Try to wrap the creation of the csvParser in a function an use it instead:

    function createCsvParser() {
        const parser = csv();
        parser.on('data', function (line) {
            [...]
        });
        return parser;
    }
    

    and change .pipe(csvParser) into .pipe(createCsvParser()).

    Hope this helps.