我正在开发一个 Firebase 函数,当新订单添加到实时数据库时会触发该函数。它做的第一件事是创建一个 pdf 并将其通过管道传输到谷歌云存储桶。
在存储桶流的 .on("finish") 事件上,下一个函数将启动,该函数应通过电子邮件将管道传输的 pdf 发送给客户。
一切似乎都有效,至少有一点。
首先我遇到了一个问题,附加的 pdf 总是空的。 (不只是空白。我还在记事本++中打开它,它确实是空的)。当我检查bucketFileStream.on("finished")函数内的doc和bucketFileSream变量时,长度均为0。在doc.end之后直接检查doc变量显示长度约为612。
然后我更改了流程,在 sendOrderEmail 函数中,我还从存储桶中新创建的文件中打开一个新的读取流。
现在我至少在附件中获得了 PDF 的一些内容,但从未获得全部内容。
当我检查上传到存储桶的 PDF 时,它看起来应该如此。
我用谷歌搜索了很多,找到了一些也针对这个主题的答案,但正如在这些问题的评论中看到的那样,它们并不完全有帮助。
- PDF 附件 NodeMailer https://stackoverflow.com/questions/37232326/pdf-attachment-nodemailer
- 在哪里生成 Firebase 数据库数据的 PDF - 移动应用程序或 Firebase 托管 Web 应用程序 https://stackoverflow.com/questions/42378751/where-to-generate-a-pdf-of-firebase-database-data-mobile-app-or-firebase-host
- 如何使用 nodemailer 将文件附加到电子邮件 https://stackoverflow.com/questions/21934667/how-to-attach-file-to-an-email-with-nodemailer
我还检查了nodemailer文档如何正确传递附件并按照文档实现它。但没有成功。
我认为邮件是在读取流完成之前发送的。
这是我使用的包版本:
- “@google-cloud/storage”:“1.5.2”
- "@types/pdfkit": "^0.7.35",
- “firebase-admin”:“5.8.0”,
- “firebase-functions”:“^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: "[email protected] /cdn-cgi/l/email-protection",
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);
});
}