Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

443
Views
Nodejs - How to detect when a readable stream has finished transfering data to writable stream

Background:

I'm using node-fpdf to generate pdf files at my server (MEAN stack), pdf files are stored temporarily on a Readable stream object like this:

// Code obtained directly from the library, 'buffer' holds all the pdf content.
const { Readable } = require('stream');
this.buffer = new Readable({ read() { } });

When I write some data over the PDF file with the library functions (let's say, to write a string) essentially what the library does is to push data on the stream like this:

this.buffer.push(someData) // Remember that this.buffer is actually a readable stream.

Once I'm done with the file I write it on disk with the library's own function which essentially pipes the readable stream into a file which of course writes it into the disk as a pdf file:

const fs = require('fs')

/** 
 * This is not the original method, I'm resuming it for readability purposes
 * @param {string} Path to which PDF file will be written.
 */
Output(path) {
    this.Close(); // Finish file with some details, nevermind
    this.buffer.pipe(fs.createWriteStream(path))
}

So the whole process goes like this:

  1. Client (Angular) provides data and makes http request to server (express).
  2. Express handles request and calls pdf generation process.
  3. Write desired data on pdf object.
  4. Call pdf.Output('/myOuputDir/mypdf.pdf') (pipe library's internal readable stream to writable (fs)).
  5. Create fs readable stream from '/myOuputDir/mypdf.pdf' (this one is handled by me).
  6. Pipe my own readable stream to response object (sometimes pdf files can be heavy so streaming the data through readable stream seems to be the best approach).

The problem:

After a couple of successfull tests I realized that sometimes step 5 breaks (Create readable stream from '/myOuputDir/mypdf.pdf') because the actual file hasn't finished being written to disk (or it hasn't even been started so it doesn't exists) because step 4 takes some time.

What have I tried

I've already tried to manually call the the library functions (on my own instance) and wrap them into a promise, so at this way I should be able to detect when the 'pipe' process has finished:

return new Promise((resolve, reject) => {
    const writable = fs.createWriteStream(filePath)
    // Handle all possible events (or at least the ones that VS code suggest)        
    writable.on('close', () => console.log('writable close'))  // maybe resolve here
    writable.on('finish', () => console.log('writable finish'))
    writable.on('open', () => console.log('writable open'))
    writable.on('pipe', () => console.log('writable pipe'))
    writable.on('ready', () => console.log('writable ready'))
    writable.on('unpipe', () => console.log('writable unpipe'))
    writable.on('drain', () => console.log('writable drain'))
    writable.on('error', (err) => reject(err))

    // Remember that pdf.buffer is the object that handles the file content, `pdf` is the library instance
    pdf.buffer.on('end', () => console.log('readable end')) // maybe resolve here
    pdf.buffer.on('error', () => console.log('readable error'))
    pdf.buffer.on('pause', () => console.log('readable pause'))
    pdf.buffer.on('readable', () => console.log('readable readable'))
    pdf.buffer.on('resume', () => console.log('readable resume'))
    pdf.buffer.on('close', () => console.log('readable close'))
    
    pdf.Close() // Library function which finishes the pdf file.
    pdf.buffer.pipe(writable) // Pipe readable pdf object to writable stream (fs)
})

I've put all this console log functions in an attempt to check all the possible events of both streams (at this way I could resolve the promise at readable's end or writable close event but for some reason they are never triggered) but the only logs I receive are:

writable pipe
readable pause
readable resume

Summarizing:

What I need is a way to detect when a readable stream (initialized by stream class, not fs) finishes it's pipe process to a writable stream, I was thinking that there must be a function/property to force the readable stream (pdf) to freeze or to make it say 'hey I've got no more data to provide you' so at this way I could handle my issue but I couldn't find any way of doing this.

An alternative:

I've also thought that I could try to pipe the pdf.buffer (remember it is a readable stream) directly to express response object and handle it at client side but after lot's of reading I couldn't find how to specify an observable with this type and also how to handle it from an Angular service.

My nodejs version is: v12.22.9

over 4 years ago · Santiago Trujillo
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!