gpt4 book ai didi

node.js - Firebase Cloud Functions - 创建 pdf、存储到存储桶并通过邮件发送

转载 作者:搜寻专家 更新时间:2023-10-31 22:41:39 25 4
gpt4 key购买 nike

我正在开发一个 Firebase 函数,它会在新订单添加到实时数据库时触发。它做的第一件事是创建一个 pdf 并将其通过管道传输到谷歌云存储桶。

在桶流的 .on("finish") 事件中,下一个函数启动,它应该通过电子邮件将管道 pdf 发送给客户。

似乎一切正常,至少有一点。

首先我遇到了问题,附件中的 pdf 总是空的。 (不只是空白,我也是用notepad++打开的,真的是一片空白)。当我检查 bucketFileStream.on("finished") 函数中的 doc 和 bucketFileSream 变量时,它们的长度均为 0。直接在 doc.end 之后检查 doc 变量显示长度约为 612。

然后我更改了流程,在 sendOrderEmail 函数中我还从存储桶中新创建的文件中打开了一个新的读取流。

现在我至少在附件中得到了 PDF 的一些内容,但没有得到全部内容。

当我检查上传到存储桶的 PDF 时,它看起来应该是这样。

我在谷歌上搜索了很多,找到了一些同样针对这个主题的答案,但正如在这些问题的评论中所看到的,它们并不是完全有用。

我还检查了 nodemailer 文档如何正确传递附件并按照文档实现它。但没有成功。

我认为邮件是在阅读流完成之前发送的。

这里是我使用的包版本:

  • “@google-cloud/storage”:“1.5.2”
  • "@types/pdfkit": "^0.7.35",
  • "firebase-admin": "5.8.0",
  • “firebase 函数”:“^0.7.3”
  • "nodemailer": "4.4.1",

任何人都可以告诉我我做错了什么或提供一个使用当前包版本的工作示例吗?

这是让我发疯的代码......

const functions = require("firebase-functions");
const admin = require("firebase-admin");
const nodemailer = require("nodemailer");
const pdfkit = require("pdfkit");
const storage = require("@google-cloud/storage")({projectId: `${PROJECT_ID}`})

const mailTransport = nodemailer.createTransport({
host: "smtp.office365.com",
port: 587,
secureConnection: false,
auth: {
user: "userName",
pass: "userPassword"
},
tls: {
ciphers: "SSLv3",
}
});

exports.added = function(event) {
const order = event.data.val();
const userId = event.params.userId;

// Load User Data by userId
return admin
.database()
.ref("/users/" +userId)
.once("value")
.then(function (snapshot) {
return generateOrderPDF(snapshot.val(), userId);
});
};

function generateOrderPDF(user, userId) {
const doc = new pdfkit();
const bucket = storage.bucket(functions.config().bucket);
const filename = `/${userId}/test-` + Date.now() + ".pdf";
const file = bucket.file(filename);
const bucketFileStream = file.createWriteStream();

// Pipe its output to the bucket
doc.pipe(bucketFileStream);

// Do creation Stuff....

doc.end();

bucketFileStream.on("finish", function () {
return sendOrderEmail(user, filename);
});

bucketFileStream.on("error", function(err) {
console.error(err);
});
}

function sendOrderEmail(user, filename) {
const email = user.email;
const firstname = user.firstName;
const mailOptions = {
from: "test@test.test",
to: email,
subject: "Order"
};

const bucket = storage.bucket(functions.config().bucket);
const file = bucket.file(filename);

mailOptions.html = mailTemplate;
mailOptions.attachments = [{
filename: "test.pdf",
content: file.createReadStream()
}];

return mailTransport.sendMail(mailOptions).then(() => {
console.log("New order email sent to:", email);
}).catch(error => {
console.error(error);
});
}

最佳答案

我的方法中的问题是在 pdfkit 库中,而不是在 nodemailer 或 firebase 中。下面几行似乎触发了结束事件。所以 pdf 是在这些行之后发送的。在对它们发表评论后,一切正常。并不是像 Hari 提到的那样从未达到终点。

/*  doc.lineCap("underline")
.moveTo(72, 321)
.lineTo(570, 321)
.stroke();*/

完成 MVP 后,我将进行根本原因分析,并将最终答案作为评论发布在此答案下方。

这是此用例的源代码的工作示例。它还确保 firebase 函数不会在所有工作完成之前完成。这是通过将事件驱动的 doc.on() 函数包装到一个 promise 中来处理的,该 promise 在调用 doc.on("end") 时解决。

exports.added = function(event) {
const order = event.data.val();
const userId = event.params.userId;

// Load User Data by userId
return admin.database().ref("/users/" + userId).once("value").then(function (snapshot) {
return generatePDF(snapshot.val(), userId);
});
};

function generatePDF(user, userId) {
const doc = new pdfkit();
const bucket = admin.storage().bucket(functions.config().moost.orderbucket);
const filename = "/${userId}/attachement.pdf";
const file = bucket.file(filename);
const bucketFileStream = file.createWriteStream();
var buffers = [];
let p = new Promise((resolve, reject) => {
doc.on("end", function() {
resolve(buffers);
});
doc.on("error", function () {
reject();
});
});

doc.pipe(bucketFileStream);
doc.on('data', buffers.push.bind(buffers));

//Add Document Text and stuff

doc.end();

return p.then(function(buffers) {
return sendMail(buffers);
});
}

function sendMail(buffers) {
const pdfData = Buffer.concat(buffers);
const mailOptions = {
from: "FromName <from@example.com>",
to: "to@example.com",
subject: "Subject",
html: mailTemplate,
attachments: [{
filename: 'attachment.pdf',
content: pdfData
}]
};

return mailTransport.sendMail(mailOptions).then(() => {
console.log("New email sent to:", "to@example.com");
}).catch(error => {
console.error(error);
});
}

关于node.js - Firebase Cloud Functions - 创建 pdf、存储到存储桶并通过邮件发送,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48310441/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com