【问题标题】:Create PDF in Firebase Cloud Functions在 Firebase Cloud Functions 中创建 PDF
【发布时间】:2018-01-02 06:47:57
【问题描述】:

我是 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文件的最佳方式吗? 我有一些要制作成 pdf 文件的 html。

【问题讨论】:

    标签: javascript pdf firebase google-cloud-functions


    【解决方案1】:

    有点晚了。

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

    希望这可以帮助任何人

    【讨论】:

      【解决方案2】:

      我在搜索与 OP 相同的内容时遇到了这个问题,但在我的特定情况下切换库不是一个选项,我对直接输出 PDF 特别感兴趣。

      在让它成功运行并与 OP 所做的比较之后,似乎缺少的只是 doc.end() 刷新数据。

      这是由 Firebase Function 输出的 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();
      
      });
      

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

      【讨论】:

        【解决方案3】:

        我尝试了 Guillaume 的建议,几乎成功了。不幸的是,Phantomjs 没有完成就退出了。

        我最终通过结合 Guillaume 的解决方案和 https://phantomjscloud.com(以及他们的库)解决了这个问题。现在这一切都像魅力一样工作。

        在“使用用户数据编译的模板”之后,替换为:

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

        【讨论】:

        • html-pdf 中有一个超时参数,如果您需要,可以多等一会儿。但 phantomjscloud 或 cloudconvert 做得很好。
        【解决方案4】:

        我也在做这个工作,在下面您可以找到一个云函数示例,该示例从托管在 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!");
              });
          });
          });
        });
        

        希望这将有助于下一个这样做的人:)

        【讨论】:

        • 嗨纪尧姆! template.html 中究竟包含什么?
        • @Mario 您必须根据 handlebarsjs.com 文档使用 html 模板。在这种情况下,这样的事情是可以的:
          {{date}} td> {{firstname}}
        【解决方案5】:

        也正在处理这个问题,为了将 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 中。

        【讨论】:

        • 我最终使用了 html-pdf,它对我来说非常有用。我会接受你的回答。
        • @user1184205 您能否更新您的答案以显示您如何使用 html-pdf?我还想在firebase中使用将html转换为pdf的东西。
        猜你喜欢
        • 1970-01-01
        • 2018-03-29
        • 1970-01-01
        • 2020-09-30
        • 2017-09-17
        • 2018-12-14
        • 2018-06-26
        • 2017-08-31
        相关资源
        最近更新 更多