tanbog
tanbog

Reputation: 610

Generate a clickable pdf from html

In Summary:

I want to dynamically generate pdfs from html. I want the resultant pdf to be searchable/clickable - NOT an image. I would like a way to do this that is compatible with vue3.

Background:

I have a Vue3 project that returns long and wordy lists of results from an API.

On the site, the results are in accordions and look great.

I want to let my users download a PDF of the results. I would like to make a minimal template for the pdf that shows an expanded (no accordions) version of the result list.

As far as I can tell there are two basic ways to do this:

  1. Create a print style in css and let users "save" the result to file as a pdf
  2. use one of a number of "html2pdf" style modules to generate the pdf

Neither approach seems to really do what I want:

routing the user to a print result leads to differing behaviour on mobile and desktop and I can't figure out how to tell the browser to just offer a pdf download.

all the various "htmltpdf" type modules I have found so far have great options and defaults but they output the pdf as an image...

I want my users to be able to select and copy the contents of the pdf - there are phone numbers and links embedded for example.

Is there some way to do this in vue; A pleasant and nice-looking download experience AND a clickable/searchable pdf?

Upvotes: 0

Views: 880

Answers (1)

Sachin Yadav
Sachin Yadav

Reputation: 313

You can use puppeteer to create pdf using html.

Step 1: Install puppeteer

npm i puppeteer

Step 2: Write a function to that renders your html into the browser and saves the page as pdf

async getPdfFromHtml(html: string): Promise<any> {
  const browser = await puppeteer.launch({ headless: true });
  
  const page = await browser.newPage();
  await page.setContent(html);
  const pdfBuffer = await page.pdf({ printBackground: true, format: 'A4' });
  await page.close();
  await browser.close();

  return pdfBuffer;
}

Step 3: Call this function wherever you want:

const html = 'your-html-template-string';

// here you will get the pdf buffer
const pdfBuffer = await getPdfFromHtml(html);

Step 4: Now you can send your pdf buffer to frontend. The following is an example of how I do in express.js

const buffer = pdfBuffer.toString('base64').replace(/([^\0]{76})/g, '$1\n') + '\n\n';

res.header('Content-type', 'application/pdf');
res.send(buffer);

Step 5: Now on frontend, all you need is call this api using an achor tag and the pdf will be downloaded.

Optional: Another alternative is to upload this buffer to aws-s3 and return the url to FE, the pdf will be downloaded once you redirect to that url.

Upvotes: 1

Related Questions