我正在尝试让Express应用程序返回生成的PDF。按照this answer,我正在尝试使用jsPDF
库以及一些伪造的全局变量。同样令人困惑的是,数据是从Postgres源中获取的。
我以前从未使用过.blob()
,我怀疑这是我没有得到回复的原因。有什么明显的我想念的地方吗?
const express = require('express')
const bodyParser = require('body-parser')
const SQL = require('sql-template-strings')
const { Client } = require('pg')
const dbConfig = require('../db')
const FormRouter = express.Router()
function saveFormAsPDF(form) {
global.window = {
document: {
createElementNS: () => {
return {}
},
},
}
global.navigator = {}
global.html2pdf = {}
global.btoa = () => {}
const jsPDF = require('jspdf') // wrapped by the fake globals
const doc = new jsPDF({
orientation: 'landscape',
format: 'a4',
})
doc.setFontSize(24)
doc.text('Form: ' + (form.identifier || 'Awaiting Retrieval'), 20, 20)
var data = doc.output()
delete global.window
delete global.html2pdf
delete global.navigator
delete global.btoa
return data
}
const getFormAsPDFByIdRoute = (req, res) => {
const client = new Client(dbConfig)
client.connect()
return client
.query(SQL`SELECT * FROM forms WHERE id = ${req.params.id}`)
.then(result => {
res
.status(result.rowCount === 0 ? 404 : 200)
.set({ 'content-type': 'application/pdf' })
.blob( saveFormAsPDF(result.rows[0]) )
})
.then(() => client.end())
}
FormRouter.route('/id/:id').get(getFormsByIdRoute)
FormRouter.route('/pdf/:id').get(getFormAsPDFByIdRoute)
exports.FormRouter = FormRouter
前段时间我有类似的要求,最终我使用了html-pdf
library。
使用该库,您只需创建一个转换流并将其通过管道传递到响应中。这样的事情(仍然需要适当的错误处理):
const html2pdf = require('html-pdf');
const getFormAsPDFByIdRoute = async(req, res) => {
const client = new Client(dbConfig);
await client.connect();
const result = await client.query(SQL `SELECT * FROM forms WHERE id = ${req.params.id}`);
if (!result.rowCount) {
return res.status(404).end();
}
const stream = await createHtlm2PdfStream(result.rows[0]);
res.contentType('application/pdf');
stream.pipe(res);
}
function createHtlm2PdfStream(html) {
return new Promise((resolve, reject) => {
html2pdf.create(html).toStream(function (err, stream) {
if (err) {
return reject(err);
}
resolve(stream);
});
});
}