So, I have written a small code to convert the html string in to pdf using the library called Wkhtmltopdf
Here is the code I have written:
index.js
const express = require('express')
const app = express()
app.use(express.json())
const port = 3000
const compiledHtml = '<h1> This is testing </h1>'
app.post('/gc', async (req, res) => {
wkhtmltopdf(compiledHtml, {
pageSize: 'A4',
orientation: 'Landscape',
marginLeft: '1mm',
marginTop: '1mm'
}).pipe(fs.createWriteStream('out.pdf')) //--->(A)
console.log('All done')
res.send(compiledHtml)
})
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
In this code, I have created REST call, POST in nature that generates the pdf and saves in a file named out.pdf (equation (A), above) in the same folder where the script is running.
But in reality I want to generate the pdf in memory, gets the buffer of the same and return the buffer back to the client so that the browser start downloading the file, I have a code as well for that, here is the code to return the buffer in response in express
snippet
......
......
res.writeHead(200, {
'Content-Type': 'application/pdf',
'Content-disposition': 'attachment;filename=certificate.pdf',
'Content-Length': buffer.length,
})
res.end(buffer)
......
......
Via above code we can written the binary data back to the client, which he can save it where-ever he wants to.
But the main problem is how do I get the buffer of the file being generated.
Please shed some light, happy coding :)
So, here is the solution of changing the buffered stream in to async await behaviour here is the generic solution that I made:
DISCLAIMER: ITS NOT A GOOD PRACTICE FOR LARGER STREAMS, BUT CAN BE USED IN CASE YOU KNOW THE RESULTANT BUFFER WOULD BE FEW KB's
const streamToBuffer = (streamObjectToRead) => {
const chunks = []
return new Promise((resolve, reject) => {
streamObjectToRead
.on('data', chunk => chunks.push(chunk))
.on('end', () => resolve(Buffer.concat(chunks)))
.on('error', err => reject(err))
})
}
Now in order to use this, you can use like this:
const someAsyncFunction = async () => {
......
...... //some code
const stream = <FUNCTION THAT RETURNS A STREAM> // like wkhtmltopdf(compiledHtml, optionsObject)
const fullBufferAfterReadingFullStream = await streamToBuffer(stream)
..... // do whatever you want to do with that buffer, eg: Writing to file, sending back to response in express framework.
}
Thanks & Happy Coding :)