How to modify a stream from request to a new respo

2019-08-19 00:55发布

I need to inject a png into a PDF using HummusJS.

In the production version of my API, I'll be receiving a post request containing a base64 that I'll convert to binary reader stream. (In the example below, I'm using a test read from a local file.)

Here's my test input stream (which is defined in a "create" object factory):

hummusReadStreamObject (filePath) {
  let fileData = fs.readFileSync(filePath).toString('hex');
  let result = []
  for (var i = 0; i < fileData.length; i+=2) {
    result.push('0x'+fileData[i]+''+fileData[i+1])
  }
  return new hummus.PDFRStreamForBuffer(result)
},

I generate a PNG (I have confirmed, the PNG is written and valid) and then perform modification during the stream's "finally" event

png.on('finish', function () {
    create.modifiedPDFResponseStream({
      pngFileName,
      readStream: create.hummusReadStreamObject('/foo/file/path'),
      res
    })
  })

the modifiedPDFResponseStream now pulls in the png and is supposed to append it to the file:

modifiedPDFResponseStream ({ pngFileName, readStream, res }) {
  const writeStream = new hummus.PDFStreamForResponse(res)
  const pdfWriter = hummus.createWriterToModify(
    readStream,
    writeStream,
    { log: `path/to/error.txt` })
  debugger
  const pageModifier = new hummus.PDFPageModifier(pdfWriter,0);
  if (pngFileName) {
    const ctx = pageModifier.startContext().getContext()
    ctx.drawImage(2, 2, `./path/to/${pngFileName}`)
    pageModifier.endContext().writePage()
    pdfWriter.end()
  }
}

I sense that I'm close to a solution, the error logs do not report any problems, but i receive the following exception when debugging via Chrome:

events.js:183 Uncaught Error: write after end
at write_ (_http_outgoing.js:622:15)
at ServerResponse.write (_http_outgoing.js:617:10)
at PDFStreamForResponse.write

is the issue something to do with the fact that the stream is being populated during the .png's .on('finish', ...) event? If so, is there a synchronous approach I could take that would mitigate this problem?

1条回答
倾城 Initia
2楼-- · 2019-08-19 01:34

inspired by the solution from @JAM in "wait for all streams to finish - stream a directory of files"

I solved this issue by having the .pngWriteStream method return a promise and having the writestream resolve on finish:

return new Promise((resolve, reject) => {
      try {
        writeStream.on('finish', resolve)
      } catch (e) {
        $.logger.error(e.message)
        reject()
      }

so instead of:

const png = create.pngWriteStream({ ... })
png.on('finish', function () {
  create.modifiedPDFResponseStream({
    pngFileName,
    readStream: create.hummusReadStreamObject('/foo/file/path'),
    res
  })
})

I await the resolution of the promise

const png = await create.pngWriteStream({
    fileName: pngFileName,
    value: '123456789' })

and the img file is available for hummus.js to write to the pdf!

create.modifiedPDFResponseStream({
    pngFileName,
    readStream: create.hummusReadStreamObject('/foo/file/path'),
    writeStream: new hummus.PDFStreamForResponse(res)
  })
查看更多
登录 后发表回答