在 Firebase Cloud Functions 中创建 PDF
Create PDF in Firebase Cloud Functions
我是 javascript 的新手,我正在尝试使用 pdfkit 从 firebase 函数制作 PDF 文件。下面是我的功能代码。
const pdfkit = require('pdfkit');
const fs = require('fs');
exports.PDFTest = functions.https.onRequest((req, res) => {
var doc = new pdfkit();
var loremIpsum = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam in...';
doc.y = 320;
doc.fillColor('black')
doc.text(loremIpsum, {
paragraphGap: 10,
indent: 20,
align: 'justify',
columns: 2
});
doc.pipe( res.status(200) )
});
函数启动后出现超时错误。
这是在 firebase 中创建 pdf 文件的最佳方式吗?
我有一些 html 想要制作成 pdf 文件。
也在做这个,为了将 PDF 保存在存储中,它是这样工作的
const myPdfFile = admin.storage().bucket().file('/test/Arbeitsvertrag.pdf');
const doc = new pdfkit();
const stream = doc.pipe(myPdfFile.createWriteStream());
doc.fontSize(25).text('Test 4 PDF!', 100, 100);
doc.end();
return res.status(200).send();
我猜你应该等到流关闭并监听错误和事情,但这是我能够制作的第一个工作示例,现在正在研究如何将图像从存储中获取到 PDF 中。
我也从事过这方面的工作,您可以在下面找到一个云函数示例,该示例从托管在 firebase 存储上的模板 HTML 创建 PDF 文件。
它使用 Hanldebars 将一些数据应用到模板,然后再次将其上传到 firebase 存储。
我这里用的是node-html-pdf.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const pdf = require('html-pdf');
const gcs = require('@google-cloud/storage')({
projectId: '[YOUR PROJECT ID]',
//key generated from here https://console.firebase.google.com/project/_/settings/serviceaccounts/adminsdk?authuser=1
keyFilename: '[YOUR KEY]'
});
const handlebars = require('handlebars');
const path = require('path');
const os = require('os');
const fs = require('fs');
const bucket = gcs.bucket('[YOUR PROJECT ID].appspot.com');
admin.initializeApp(functions.config().firebase);
exports.helloWorld = functions.https.onRequest((request, response) => {
// data to apply to template file
const user = {
"date": new Date().toISOString(),
"firstname" : "Guillaume",
};
const options = {
"format": 'A4',
"orientation": "portrait"
};
const localTemplate = path.join(os.tmpdir(), 'localTemplate.html');
const localPDFFile = path.join(os.tmpdir(), 'localPDFFile.pdf');
bucket.file('template.html').download({ destination: localTemplate }).then(() => {
console.log("template downloaded locally");
const source = fs.readFileSync(localTemplate, 'utf8');
const html = handlebars.compile(source)(user);
console.log("template compiled with user data", html);
pdf.create(html, options).toFile(localPDFFile, function(err, res) {
if (err){
console.log(err);
return response.send("PDF creation error");
}
console.log("pdf created locally");
return bucket.upload(localPDFFile, { destination: user.name + '.pdf', metadata: { contentType: 'application/pdf'}}).then(() => {
response.send("PDF created and uploaded!");
}).catch(error => {
console.error(error);
response.send("PDF created and uploaded!");
});
});
});
});
希望这对下一个这样做有帮助:)
我尝试了 Guillaume 的建议,结果几乎成功了。不幸的是,Phantomjs 没有完成就退出了。
我最终通过结合 Guillaume 的解决方案和 https://phantomjscloud.com(以及他们的库)解决了这个问题。现在一切都很顺利。
在 "template compiled with user data" 之后替换为:
const phantomJsCloud = require("phantomjscloud");
const browser = new phantomJsCloud.BrowserApi([YOURPHANTOMJSCLOUDAPIKEY]);
var pageRequest = { content: html, renderType: "pdf" };
// Send our HTML to PhantomJS to convert to PDF
return browser.requestSingle(pageRequest)
.then(function (userResponse) {
if (userResponse.statusCode != 200) {
console.log("invalid status code" + userResponse.statusCode);
} else {
console.log('Successfully generated PDF');
// Save the PDF locally
fs.writeFile(localPDFFile, userResponse.content.data, {
encoding: userResponse.content.encoding,
}, function (err) {
// Upload the file to our cloud bucket
return pdfBucket.upload(localPDFFile, { destination: 'desired-filename.pdf', metadata: { contentType: 'application/pdf'}}).then(() => {
console.log('bucket upload complete: '+ localPDFFile);
}).catch(error => {
console.error('bucket upload error:', error);
});
});
}
});
我 运行 在搜索与 OP 相同的内容时进入这个问题,但在我的特定情况下,切换库不是一个选项,我对直接输出 PDF 特别感兴趣。
在让它成功运行并与 OP 所做的比较之后,似乎缺少的只是
doc.end()
刷新数据。
这是 Firebase 函数输出的 PDFKit 演示:
const PDFDocument = require('pdfkit');
exports.PDFTest = functions.https.onRequest((req, res) => {
var doc = new PDFDocument();
// draw some text
doc.fontSize(25)
.text('Here is some vector graphics...', 100, 80);
// some vector graphics
doc.save()
.moveTo(100, 150)
.lineTo(100, 250)
.lineTo(200, 250)
.fill("#FF3300");
doc.circle(280, 200, 50)
.fill("#6600FF");
// an SVG path
doc.scale(0.6)
.translate(470, 130)
.path('M 250,75 L 323,301 131,161 369,161 177,301 z')
.fill('red', 'even-odd')
.restore();
// and some justified text wrapped into columns
doc.text('And here is some wrapped text...', 100, 300)
.font('Times-Roman', 13)
.moveDown()
.text("... lorem ipsum would go here...", {
width: 412,
align: 'justify',
indent: 20,
columns: 2,
height: 300,
ellipsis: true
});
doc.pipe(res.status(200));
doc.end();
});
这是一个非常简单的示例,可能需要适当的 headers 才能发送,但它可以在现代浏览器中正常工作。
我希望这可以帮助任何寻找相同的人。
有点晚了。
https://edgecoders.com/generating-a-pdf-with-express-in-node-js-d3ff5107dff1
import * as functions from 'firebase-functions';
import * as PDFDocument from 'pdfkit';
export const yourFunction = functions
.https
.onRequest((req, res) => {
const doc = new PDFDocument();
let filename = req.body.filename;
// Stripping special characters
filename = encodeURIComponent(filename) + '.pdf';
// Setting response to 'attachment' (download).
// If you use 'inline' here it will automatically open the PDF
res.setHeader('Content-disposition', 'attachment; filename="' + filename + '"');
res.setHeader('Content-type', 'application/pdf');
const content = req.body.content;
doc.y = 300;
doc.text(content, 50, 50);
doc.pipe(res);
doc.end();
});
希望对大家有所帮助
我是 javascript 的新手,我正在尝试使用 pdfkit 从 firebase 函数制作 PDF 文件。下面是我的功能代码。
const pdfkit = require('pdfkit');
const fs = require('fs');
exports.PDFTest = functions.https.onRequest((req, res) => {
var doc = new pdfkit();
var loremIpsum = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam in...';
doc.y = 320;
doc.fillColor('black')
doc.text(loremIpsum, {
paragraphGap: 10,
indent: 20,
align: 'justify',
columns: 2
});
doc.pipe( res.status(200) )
});
函数启动后出现超时错误。 这是在 firebase 中创建 pdf 文件的最佳方式吗? 我有一些 html 想要制作成 pdf 文件。
也在做这个,为了将 PDF 保存在存储中,它是这样工作的
const myPdfFile = admin.storage().bucket().file('/test/Arbeitsvertrag.pdf');
const doc = new pdfkit();
const stream = doc.pipe(myPdfFile.createWriteStream());
doc.fontSize(25).text('Test 4 PDF!', 100, 100);
doc.end();
return res.status(200).send();
我猜你应该等到流关闭并监听错误和事情,但这是我能够制作的第一个工作示例,现在正在研究如何将图像从存储中获取到 PDF 中。
我也从事过这方面的工作,您可以在下面找到一个云函数示例,该示例从托管在 firebase 存储上的模板 HTML 创建 PDF 文件。 它使用 Hanldebars 将一些数据应用到模板,然后再次将其上传到 firebase 存储。 我这里用的是node-html-pdf.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const pdf = require('html-pdf');
const gcs = require('@google-cloud/storage')({
projectId: '[YOUR PROJECT ID]',
//key generated from here https://console.firebase.google.com/project/_/settings/serviceaccounts/adminsdk?authuser=1
keyFilename: '[YOUR KEY]'
});
const handlebars = require('handlebars');
const path = require('path');
const os = require('os');
const fs = require('fs');
const bucket = gcs.bucket('[YOUR PROJECT ID].appspot.com');
admin.initializeApp(functions.config().firebase);
exports.helloWorld = functions.https.onRequest((request, response) => {
// data to apply to template file
const user = {
"date": new Date().toISOString(),
"firstname" : "Guillaume",
};
const options = {
"format": 'A4',
"orientation": "portrait"
};
const localTemplate = path.join(os.tmpdir(), 'localTemplate.html');
const localPDFFile = path.join(os.tmpdir(), 'localPDFFile.pdf');
bucket.file('template.html').download({ destination: localTemplate }).then(() => {
console.log("template downloaded locally");
const source = fs.readFileSync(localTemplate, 'utf8');
const html = handlebars.compile(source)(user);
console.log("template compiled with user data", html);
pdf.create(html, options).toFile(localPDFFile, function(err, res) {
if (err){
console.log(err);
return response.send("PDF creation error");
}
console.log("pdf created locally");
return bucket.upload(localPDFFile, { destination: user.name + '.pdf', metadata: { contentType: 'application/pdf'}}).then(() => {
response.send("PDF created and uploaded!");
}).catch(error => {
console.error(error);
response.send("PDF created and uploaded!");
});
});
});
});
希望这对下一个这样做有帮助:)
我尝试了 Guillaume 的建议,结果几乎成功了。不幸的是,Phantomjs 没有完成就退出了。
我最终通过结合 Guillaume 的解决方案和 https://phantomjscloud.com(以及他们的库)解决了这个问题。现在一切都很顺利。
在 "template compiled with user data" 之后替换为:
const phantomJsCloud = require("phantomjscloud");
const browser = new phantomJsCloud.BrowserApi([YOURPHANTOMJSCLOUDAPIKEY]);
var pageRequest = { content: html, renderType: "pdf" };
// Send our HTML to PhantomJS to convert to PDF
return browser.requestSingle(pageRequest)
.then(function (userResponse) {
if (userResponse.statusCode != 200) {
console.log("invalid status code" + userResponse.statusCode);
} else {
console.log('Successfully generated PDF');
// Save the PDF locally
fs.writeFile(localPDFFile, userResponse.content.data, {
encoding: userResponse.content.encoding,
}, function (err) {
// Upload the file to our cloud bucket
return pdfBucket.upload(localPDFFile, { destination: 'desired-filename.pdf', metadata: { contentType: 'application/pdf'}}).then(() => {
console.log('bucket upload complete: '+ localPDFFile);
}).catch(error => {
console.error('bucket upload error:', error);
});
});
}
});
我 运行 在搜索与 OP 相同的内容时进入这个问题,但在我的特定情况下,切换库不是一个选项,我对直接输出 PDF 特别感兴趣。
在让它成功运行并与 OP 所做的比较之后,似乎缺少的只是
doc.end()
刷新数据。
这是 Firebase 函数输出的 PDFKit 演示:
const PDFDocument = require('pdfkit');
exports.PDFTest = functions.https.onRequest((req, res) => {
var doc = new PDFDocument();
// draw some text
doc.fontSize(25)
.text('Here is some vector graphics...', 100, 80);
// some vector graphics
doc.save()
.moveTo(100, 150)
.lineTo(100, 250)
.lineTo(200, 250)
.fill("#FF3300");
doc.circle(280, 200, 50)
.fill("#6600FF");
// an SVG path
doc.scale(0.6)
.translate(470, 130)
.path('M 250,75 L 323,301 131,161 369,161 177,301 z')
.fill('red', 'even-odd')
.restore();
// and some justified text wrapped into columns
doc.text('And here is some wrapped text...', 100, 300)
.font('Times-Roman', 13)
.moveDown()
.text("... lorem ipsum would go here...", {
width: 412,
align: 'justify',
indent: 20,
columns: 2,
height: 300,
ellipsis: true
});
doc.pipe(res.status(200));
doc.end();
});
这是一个非常简单的示例,可能需要适当的 headers 才能发送,但它可以在现代浏览器中正常工作。 我希望这可以帮助任何寻找相同的人。
有点晚了。
https://edgecoders.com/generating-a-pdf-with-express-in-node-js-d3ff5107dff1
import * as functions from 'firebase-functions';
import * as PDFDocument from 'pdfkit';
export const yourFunction = functions
.https
.onRequest((req, res) => {
const doc = new PDFDocument();
let filename = req.body.filename;
// Stripping special characters
filename = encodeURIComponent(filename) + '.pdf';
// Setting response to 'attachment' (download).
// If you use 'inline' here it will automatically open the PDF
res.setHeader('Content-disposition', 'attachment; filename="' + filename + '"');
res.setHeader('Content-type', 'application/pdf');
const content = req.body.content;
doc.y = 300;
doc.text(content, 50, 50);
doc.pipe(res);
doc.end();
});
希望对大家有所帮助