Which package do you use to generate PDFs in Meteor?

I wanted to convert my markdown content to PDF and have it downloaded via the browser. This thread provided me with my start point so thanks everybody :thumbsup:

After a bit of investigation I found the npm package markdown-pdf to be an excellent choice for me and one that got me to a satisfactory working solution.

You can read a detailed description plus the Meteor ready code (coffeescript) on stack overflow: How do I generate and download a PDF from markdown using Meteor

2 Likes

Iā€™m not sure but, after reading this post it seems like a big hazzle to export data to a pdf document?

Iā€™ve recently picked up a project that demands an export function and am not entirely sure how to execute it.

Try this package, hereā€™s the repo.

You should provide more details about your requirements, if itā€™s server side or client side.

The package that iā€™ve mentioned above is capable of generating pdf from data form submission, but the limitation of it is generate pdf on a table dynamically, actually, I have an open issue regarding this, issue#4.

1 Like

Cool, thanks!

Client-side should be good enough since all the client has requested is to be able to export a displayed list of items by the click of a button and send it through an email service.

The package you linked looks like it would do just the job and Iā€™ll give it a try at the office tomorrow =) Thanks!

I am sure you have figured this out by now. Just in case for some one else who is thinking the same. The code assumes you have iron:router installed. If you donā€™t you can use the method @ryanswapp has mentioned.

did you ever manage to solve this? sadly, iā€™m always getting [Error: PhantomJS exited with return value 2]ā€¦

Hey, I tried a few different packages from atmosphere but in the end none quite worked out for me. So I did it the old way: Downloaded PDFKit and a certain ā€œblob-streamā€ package (youā€™ll find a link to both and instructions on pdfkit.org). Put both inside public/ and then <script> tags on the <head>
Thatā€™s it. Now you can create and compose client side pdfā€™s and output them to a blobURL.
The PDFKit documentation is excellent so take a look and youā€™ll be able to use it easily.
Note: the unit of measure on most of these pdf packages is pt, so keep that in mind.
http://www.unitconversion.org/typography/postscript-points-to-pixels-x-conversion.html Hereā€™s a site to convert units.

Hi, Iā€™m not sure if youā€™ve solved your problem, but perhaps you can try this: You can turn things from a <canvas> into an image with HTMLCanvasElement.toDataURL() or HTMLCanvasElement.toBlob(). The latter doesnā€™t work on Chrome yet, but both are native APIā€™s

It might be a bit of work, but if you can compose whatever you have to create an image of, inside a canvas, then you can use that method on it. Rember that canvas accepts text. You can then access the output image by simply opening the dataURL or blobURL that is generated, or using it as the src attribute on an <img> .
Hereā€™s info on the API https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL

Hereā€™s a tutorial showing how to put DOM objects into a canvas: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Drawing_DOM_objects_into_a_canvas

Take a look at my two posts below. Perhaps they can help. One is about creating PDFā€™s. The other about creating images out o html.

hey thanks for your answer. i also had a look at pdfkit first, it seems really powerful but I think I remember that it is a 1MB lib :frowning:

why this.route?
maybe Router.route?
what is context for this.route?

Iā€™ve enjoyed using jsReport for my PDF needs

2 Likes

Do you run that on your own server or using their cloud? Any tips?

I run my own server at first I use their free version and then I purchase their license. I create templates using handlebars which makes it very easy since itā€™s so somewhere to meteor it even has the ability to run Scripts.

1 Like

@badmark, Interesting for your issue.
Could have any example to use with Meteor? I base on Vue

I use the jsreport NPM module. Itā€™s a fairly straight forward approach. Documentation gave me everything I needed to implement.

1 Like

I tried to read documents, but donā€™t understand.

Quick pseudo gist of what iā€™ve done in the past.

On the server
Use Meteor SSR to generate a template for the pdf on the server
SSR.compileTemplate('myTemplate')
then .
SSR.render('myTemplate).
Will give you an html_string of the pdf template.

Then I have a meteor.wrapAsync method
that takes that html_string passes it to webshot to take a screenshot of the rendered PDF (via phatomjs), access the file with FS and then return the file as base64 string in a callback.

var foo = Meteor.wrapAsync(function(html_string,fileName,callback) {
 webshot(html_string, fileName, options, function() {
   fs.readFile(fileName, function (err, data) { 
      fs.unlinkSync(fileName); 
      callback(err, {response: data});
   }
} 

On the client
I then return that base64 string to client, and in my case convert the base64 string into a Blob, create a URL, and open a preview window.

Meteor.call('openPdf, function(err,res) {
        //var view = convert res from base64 to blob ....
        var blob = new Blob( [view], { type: "application/pdf" });
        var url = URL.createObjectURL(blob);
        window.open(url);
}

HI @badmark and @Citylims , I tried install jsrport, it work fine.
But now I would like to render api of Excel, PDF to my Vue Component (Meteor + Vue)

// Server
import { WebApp } from 'meteor/webapp'
import express from 'express'
import request from 'request'
const appEx = express()

appEx.get('/api/jsreport', (req, res) => {
  let body = {
    template: {
      shortid: 'SJtztNP4Q',
    },
    options: { },
  }
  let options = {
    uri: 'http://localhost:5488/api/report',
    method: 'POST',
    json: body,
  }

  request(options).pipe(res)
})

WebApp.connectHandlers.use(appEx)
-----------
<template>
  <div>
    <p>
      <el-button @click="getReport">Get Report</el-button>
    </p>
    {{ report }}
  </div>
</template>
...
methods: {
    getReport() {
      axios
        .get('/api/jsreport')
        .then(function(res) {
          this.report = res
        })
        .catch(function(error) {
          console.log(error)
        })
    },

But donā€™t work