将原始pdf流式传输到客户端需要花费大量时间



OS:ubuntu 20.04Nodejs:14.18.3npm:6.14.15pdfMake:0.1.72(用于从文件或数据库查询创建pdf文件(

目前,我尝试从一个文件中制作一个pdf(它可能是一个数据库查询(,我想通过流将其发送到客户端。向用户发送数据块以避免缓冲服务器的ram。我已经把它发送给用户了,但下载一个300kb的pdf需要很长时间,几乎需要15秒。我似乎在客户端中接收到的每个块都是16kb,这是res对象不可更改的(我认为(大小

我使用来自pdfMake库的可读流,并尝试管道进入res对象(express(。

以下是创建文件(pdfMake库(

let bigfile = fs.readFileSync('./bigfile.txt', 'utf8');
function docDefinition() {
let content = [{
text: 'This is a header',
alignment: 'center',
fontSize: 25,
margin: [0,0,0,0]
}]

content.push({ text: bigfile })
let docDefinition = {
content: content
}
return docDefinition
}

在这里,我生成行pdf本身";作为可读流";并在回叫中将其传递到我的快速路线

const generatePdf = (docDefinition, callback) => {
try {
const fontDescriptors = {
Roboto: {
normal: path.join(__dirname, '/fonts/Roboto-Regular.ttf'),
bold: path.join(__dirname, '/fonts/Roboto-Medium.ttf'),
italics: path.join(__dirname, '/fonts/Roboto-Italic.ttf'),
bolditalics: path.join(__dirname, '/fonts/Roboto-MediumItalic.ttf'),
},
};
const printer = new pdfMakePrinter(fontDescriptors);
const doc = printer.createPdfKitDocument(docDefinition);
/* something to add, **const = doc** has its own event for streaming (I guess)
doc.on('data', chunk => {
// send current chunk to client somehow
})
doc.on('end', chunk => {
// finished the streaming
})        
*/
callback(doc)
} catch (error) {
throw error;        
}
}

我的主服务器.js,如果我试图以一种chuncked transafer方式将pdf发送给用户

app.get('/file', (req, res) => {
generatePdf(
docDefinition, 
readable => {
res.set({
"Content-Type": "application/pdf",
"Transfer-Encoding": "chunked",
"Connection": "keep-alive"
});
console.log('res.HighWaterMark', res.writableHighWaterMark);
console.log('readable highWaterMark', readable._readableState.highWaterMark);
readable.pipe(res)
readable.end()
})
})

我只是试着在浏览器中播放视频,这很容易,因为fs内部模块。但在这里,我使用了一个外部库(pdfmake(来制作可读流。我对node中的流非常初学者。我非常感谢任何帮助解决这个特殊问题的建议S

源代码可以在这里获得资金:https://github.com/biagiola/streamPDFtoClient

您不需要Readable,因为Express的Response是基于节点的http.serverResponse,它是一个流。

编辑:只需将respose传递给generatePdf,然后在那里使用doc.pipe(callback(和doc.end((。我在示例代码中将回调改为res

const pdfMakePrinter = require('pdfmake');
const generatePdf = (docDefinition, res) => {
// ... setup code here.
const doc = printer.createPdfKitDocument(docDefinition);
doc.pipe(res);
doc.end();
}

server.js:

app.get('/file', (req, res) => {
generatePdf(
docDefinition, 
res);
});

进一步编辑:

这可能是库的速度,你可能不得不接受它。当我使用以下代码来计时生成过程(删除原始文档的创建(时,我在系统上的时间大约为7.25秒。

app.get('/file', (req, res, next) => {
res.attachment('myFancyPdf.pdf')
const start = Date.now();
generatePdfBase64(
docDefinition,
res);
next(console.log(Date.now() - start))
});

我的开发系统是一个英特尔i7-10700T CPU,具有32GB的RAM。

最新更新