Javascript 为什么节点Pdfkit会在我的代码中偶尔创建损坏的文件?
我有一个函数,可以创建一个pdf文件,并使用Javascript 为什么节点Pdfkit会在我的代码中偶尔创建损坏的文件?,javascript,node.js,asynchronous,async-await,pdfkit,Javascript,Node.js,Asynchronous,Async Await,Pdfkit,我有一个函数,可以创建一个pdf文件,并使用pdfkit和nodemailer将其发送到电子邮件,有时我会收到一个无法打开的文件。不知道为什么会发生这种情况,为什么大部分时间都有效?我没有注意到它失败时的任何特定情况,其中似乎没有任何公式(文本长度等)。有人能指出我的pdf创建代码(比如async/await)中是否存在一些明显的问题吗 我也经历过同样的问题,经过调查,我在 PDFKit实际上不知道何时所有数据都已刷新到 您正在写入的任何流(文件、http响应等)。自从 PDFKit无法访问它正
pdfkit
和nodemailer
将其发送到电子邮件,有时我会收到一个无法打开的文件。不知道为什么会发生这种情况,为什么大部分时间都有效?我没有注意到它失败时的任何特定情况,其中似乎没有任何公式(文本长度等)。有人能指出我的pdf创建代码(比如async/await)中是否存在一些明显的问题吗
我也经历过同样的问题,经过调查,我在 PDFKit实际上不知道何时所有数据都已刷新到 您正在写入的任何流(文件、http响应等)。自从 PDFKit无法访问它正在通过管道传输的实际可写流 to(PDFKit本身是一个可读流,您可以设置可写流 部分),它只知道何时完成了向 不管是谁在读书。可能过了一段时间,可写的 流实际上将其内部缓冲区刷新到实际 目的地 我相信这并不像听“结束”节目那么简单 在写流上,特别是在出现错误的情况下,因此 实现了以下返回承诺的函数
函数savePdfToFile(pdf:PDFKit.PDFDocument,文件名:string):Promise{
返回新承诺((解决、拒绝)=>{
//确定PDF何时已成功完成编写
//我们需要确认以下两个条件:
//
//1.写入流已关闭
//2.同步调用了PDFDocument.end(),未引发错误
让pendingStepCount=2;
const stepFinished=()=>{
如果(--pendingStepCount==0){
解决();
}
};
const writeStream=fs.createWriteStream(文件名);
在('close',stepFinished'上写入团队);
pdf.pipe(writeStream);
pdf.end();
步骤完成();
});
}
不是直接调用.end(),而是调用此函数并传递
pdf文档和文件名
这应正确处理以下情况:
PDF生成成功错误在PDF.end()中引发
写入流已关闭写入后在pdf.end()中引发错误
溪流已经关闭
因此,最终看来,有时服务器为您创建文件的速度不够快,在实施此解决方案后,我的响应时间确实增加了1秒,并且消除了这种损坏行为看不到您在任何地方返回流:)
exports.sendTranscriptionToEmail = async (req, res) => {
let finalText = [];
let nickColorsArray = [];
const doc = new PDFDocument();
let filename = req.body.sessionName;
let text = [];
if (!filename || typeof filename != "string") {
return res.status(400).send({ message: "Incorrect Information!" });
}
// here I get the data from the database
try {
const rows = await knex("transcriptions").select("*").where({
conversation_id: filename,
});
if (!rows) {
return res.status(400).send({ message: "Transcription not found" });
}
// Stripping special characters
filename = encodeURIComponent(filename) + ".pdf";
res.setHeader(
"Content-disposition",
'attachment; filename="' + filename + '"'
);
res.setHeader("Content-type", "application/pdf");
doc.pipe(fs.createWriteStream(filename));
doc.fontSize(18).fillColor("black").text("Participants:", {
width: 410,
align: "center",
});
doc.moveDown();
nickColorsArray.forEach((n) => {
doc.fontSize(14).fillColor(n.color).text(n.nick, {
width: 410,
align: "center",
});
});
doc.moveDown();
doc.moveDown();
doc.fontSize(18).fillColor("black").text("Transcription:", {
width: 410,
align: "center",
});
doc.moveDown();
finalText.forEach((f) => {
doc
.fontSize(14)
.fillColor(f.color)
.text(f.word + " ", {
width: 410,
continued: true,
});
});
doc.end();
} catch (err) {
console.log("Something went wrong: ", err.message);
}
function savePdfToFile(pdf : PDFKit.PDFDocument, fileName : string) : Promise<void> {
return new Promise<void>((resolve, reject) => {
// To determine when the PDF has finished being written successfully
// we need to confirm the following 2 conditions:
//
// 1. The write stream has been closed
// 2. PDFDocument.end() was called syncronously without an error being thrown
let pendingStepCount = 2;
const stepFinished = () => {
if (--pendingStepCount == 0) {
resolve();
}
};
const writeStream = fs.createWriteStream(fileName);
writeStream.on('close', stepFinished);
pdf.pipe(writeStream);
pdf.end();
stepFinished();
});
}