Javascript 在Firebase云函数中创建PDF

Javascript 在Firebase云函数中创建PDF,javascript,pdf,firebase,google-cloud-functions,Javascript,Pdf,Firebase,Google 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 ame

我是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存储上。 我在这里使用了节点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!");
      });
  });
  });
});

希望这能帮助下一位这样做:)

我尝试了纪尧姆的建议,它几乎让我达到了目的。不幸的是,Phantomjs没有完成就退出了

我最终通过结合纪尧姆的解决方案和(以及他们的库)解决了这个问题。现在一切都像一个符咒一样起作用

在“使用用户数据编译模板”之后,替换以下内容:

 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();

});
这是一个非常简单的示例,可能需要发送适当的头,但它在现代浏览器中仍能正常工作。 我希望这能帮助任何人寻找同样的东西。

有点晚了


希望这可以帮助任何人

我最终使用了html pdf,它对我来说非常有用。我会接受你的答案。@user1184205你能更新你的答案,说明你是如何使用html pdf的吗?我也想在firebase中使用一些将html转换为pdf的东西。嗨,纪尧姆!template.html中到底包含什么?@Mario根据文档,您必须使用html模板。在这种情况下,类似这样的内容是可以的:{{date}{{firstname}}但是,在模板显然已正确编译之后,我得到以下错误。。。错误:html pdf:pdf生成超时。Phantom.js脚本未退出。节点html pdf上存在
超时设置。也许会有帮助。用于生成PDF的phantomjs也有点旧,不要使用
let
或新的javascript之类的东西,否则你会得到一个空白的PDF或最糟糕的,这种错误..如果你有多个用户使用该应用程序生成PDF文件呢?我们如何知道哪些PDF属于每个用户,以及如何在上传到Firebase存储后清理临时文件?@GuillaumeGendre我能够将模板编译成html,但
html PDF
忽略了
中的内容。。。我该怎么办?html pdf中有一个timeout参数,如果您需要它,可以再等待一点。但phantomjscloud或cloudconvert的工作做得很好。

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();
  });