Estoy usando node-fpdf para generar archivos pdf en mi servidor (pila MEAN), los archivos pdf se almacenan temporalmente en un objeto de flujo legible como este:
// Code obtained directly from the library, 'buffer' holds all the pdf content. const { Readable } = require('stream'); this.buffer = new Readable({ read() { } });Cuando escribo algunos datos sobre el archivo PDF con las funciones de la biblioteca (digamos, para escribir una cadena), esencialmente lo que hace la biblioteca es enviar datos a la transmisión de esta manera:
this.buffer.push(someData) // Remember that this.buffer is actually a readable stream.Una vez que termino con el archivo, lo escribo en el disco con la propia función de la biblioteca, que esencialmente canaliza el flujo legible a un archivo que, por supuesto, lo escribe en el disco como un archivo pdf:
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)) }Así que todo el proceso es así:
pdf.Output('/myOuputDir/mypdf.pdf') (transfiera el flujo legible interno de la biblioteca a escritura (fs)).'/myOuputDir/mypdf.pdf' (este lo manejo yo). Después de un par de pruebas exitosas, me di cuenta de que a veces el paso 5 se interrumpe (Crear flujo legible desde '/myOuputDir/mypdf.pdf' ) porque el archivo real no ha terminado de escribirse en el disco (o ni siquiera se ha iniciado, por lo que no existe) porque el paso 4 lleva algún tiempo.
Ya intenté llamar manualmente a las funciones de la biblioteca (en mi propia instancia) y envolverlas en una promesa, por lo que de esta manera debería poder detectar cuándo finalizó el proceso de 'tubería':
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) }) Puse todas estas funciones de registro de la consola en un intento de verificar todos los eventos posibles de ambas transmisiones (de esta manera podría resolver la promesa al end de la lectura o el evento de close de la escritura, pero por alguna razón nunca se activan) pero los únicos registros recibo son:
writable pipe readable pause readable resumeLo que necesito es una forma de detectar cuándo un flujo legible (inicializado por clase de flujo, no fs) termina su proceso de canalización a un flujo de escritura, estaba pensando que debe haber una función/propiedad para forzar el flujo legible (pdf) para congelar o hacer que diga 'oye, no tengo más datos para proporcionarte', de esta manera podría manejar mi problema, pero no pude encontrar ninguna forma de hacerlo.
También pensé que podría intentar canalizar el pdf.buffer (recuerde que es un flujo legible) directamente para expresar el objeto de respuesta y manejarlo en el lado del cliente, pero después de leer mucho no pude encontrar cómo especificar un observable con este tipo y también cómo manejarlo desde un servicio Angular.
Mi versión de nodejs es: v12.22.9