缓冲区中的 wkhtmltopdf 响应

wkhtmltopdf response in a buffer

所以,我编写了一个小代码,使用名为 Wkhtmltopdf

的库将 html 字符串转换为 pdf

这是我写的代码:

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}!`))

在这段代码中,我创建了 REST 调用POST 本质上生成 pdf 并保存在名为 out.pdf 的文件(上面的等式 (A))位于脚本所在的同一文件夹中 运行.

但实际上我想在内存中生成pdf,获取缓冲区相同的 return 将缓冲区返回给客户端 以便浏览器开始下载文件,我也有一个代码,这里是 return buffer in response in express

片段

......
......
res.writeHead(200, {
  'Content-Type': 'application/pdf',
  'Content-disposition': 'attachment;filename=certificate.pdf',
  'Content-Length': buffer.length,
})
res.end(buffer)
......
......

通过上面的代码我们可以将二进制数据写回给客户端,他可以把它保存在任何他想保存的地方。

但主要问题是如何获取正在生成的文件的缓冲区。

请说明,编码愉快:)

我建议简单地将 wkhtmltopdf 的输出传输到 res 对象,这样就不必完全创建缓冲区。

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) => {
   res.writeHead(200, {
      'Content-Type': 'application/pdf',
      'Content-disposition': 'attachment;filename=certificate.pdf',
   });

   wkhtmltopdf(compiledHtml, {
      pageSize: 'A4',
      orientation: 'Landscape',
      marginLeft: '1mm',
      marginTop: '1mm'
   }).pipe(res)
   console.log('All done')
});
app.listen(port, () => console.log(`Example app listening on port ${port}!`))

所以,这里是将缓冲流更改为异步等待行为的解决方案,这里是我制定的通用解决方案:

免责声明:对于较大的数据流来说,这不是一个好的做法,但如果您知道结果缓冲区会很少 KB,则可以使用它

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))
   }) 
}

现在为了使用这个,你可以这样使用:

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.
}

谢谢,编码愉快:)