Skip to content

Instantly share code, notes, and snippets.

@uatisdeproblem
Last active August 29, 2023 12:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save uatisdeproblem/c4204778ed983f99bbbc18758ac1aed0 to your computer and use it in GitHub Desktop.
Save uatisdeproblem/c4204778ed983f99bbbc18758ac1aed0 to your computer and use it in GitHub Desktop.
AWS Lambda: html2pdf (IDEA)
'use strict';
//
// AWS Lambda: idea_html2pdf (Node.js >= 18)
// File: index.js
// -- ITER IDEA, 2023.
// This function's source code is defined in the following GitHub Gist:
// https://gist.github.com/uatisdeproblem/c4204778ed983f99bbbc18758ac1aed0
//
// required through AWS Lambda layer
const puppeteer = require('puppeteer-core');
const chromium = require('@sparticuz/chromium');
chromium.setHeadlessMode = true;
chromium.setGraphicsMode = false;
exports.handler = async (event, _, callback) => {
const params = {
body: event.body ?? '',
header: event.header ?? '',
footer: event.footer ?? '',
pdfOptions: event.pdfOptions ?? {}
};
try {
const data = await html2pdf(params);
callback(null, data);
} catch (err) {
callback(err);
}
};
async function html2pdf(params) {
let browser;
try {
params.pdfOptions.displayHeaderFooter = Boolean(params.header || params.footer);
params.pdfOptions.headerTemplate = params.header;
params.pdfOptions.footerTemplate = params.footer;
params.pdfOptions.format = params.pdfOptions.format ?? 'A4';
params.pdfOptions.printBackground =
params.pdfOptions.printBackground === undefined ? true : params.pdfOptions.printBackground;
params.pdfOptions.margins = params.pdfOptions.margins ?? { top: '2cm', right: '1cm', bottom: '2cm', left: '1cm' };
const browser = await puppeteer.launch({
args: chromium.args.concat('--font-render-hinting=none'),
defaultViewport: chromium.defaultViewport,
executablePath: await chromium.executablePath(),
headless: chromium.headless,
});
const page = await browser.newPage();
await page.setContent(params.body, { waitUntil: 'networkidle2' });
await page.emulateMediaType('screen');
const pdfData = await page.pdf(params.pdfOptions);
if (browser) await browser.close();
return pdfData.toString('base64');
} catch(error) {
if (browser) await browser.close();
throw error;
}
}
'use strict';
//
// AWS Lambda: idea_html2pdf_viaS3Bucket (Node.js >= 18)
// Alternate version of idea_html2pdf that uses an intermediate S3 bucket to avoid Lambda's payload limits.
// File: index.js
// -- ITER IDEA, 2023.
// This function's source code is defined in the following GitHub Gist:
// https://gist.github.com/uatisdeproblem/c4204778ed983f99bbbc18758ac1aed0
//
// required through AWS Lambda layer
const puppeteer = require('puppeteer-core');
const chromium = require('@sparticuz/chromium');
chromium.setHeadlessMode = true;
chromium.setGraphicsMode = false;
const { S3Client } = require('@aws-sdk/client-s3');
const { Upload } = require('@aws-sdk/lib-storage');
const s3 = new S3Client();
exports.handler = async (event, _, callback) => {
const params = {
body: event.body ?? '',
header: event.header ?? '',
footer: event.footer ?? '',
pdfOptions: event.pdfOptions ?? {},
s3Bucket: event.s3Bucket,
s3Prefix: event.s3Prefix
};
try {
const data = await html2pdfViaS3Bucket(params);
callback(null, data);
} catch (err) {
callback(err);
}
};
async function html2pdfViaS3Bucket(params) {
let browser;
try {
params.pdfOptions.displayHeaderFooter = Boolean(params.header || params.footer);
params.pdfOptions.headerTemplate = params.header;
params.pdfOptions.footerTemplate = params.footer;
params.pdfOptions.format = params.pdfOptions.format ?? 'A4';
params.pdfOptions.printBackground =
params.pdfOptions.printBackground === undefined ? true : params.pdfOptions.printBackground;
params.pdfOptions.margins = params.pdfOptions.margins ?? { top: '2cm', right: '1cm', bottom: '2cm', left: '1cm' };
const browser = await puppeteer.launch({
args: chromium.args.concat('--font-render-hinting=none'),
defaultViewport: chromium.defaultViewport,
executablePath: await chromium.executablePath(),
headless: chromium.headless,
});
const page = await browser.newPage();
await page.setContent(params.body, { waitUntil: 'networkidle2' });
await page.emulateMediaType('screen');
const pdfData = await page.pdf(params.pdfOptions);
const s3Bucket = params.s3Bucket ?? 'idea-downloads';
const s3Prefix = params.s3Prefix ?? 'html2pdf';
const s3ParamsToRetrievePDF = await uploadPDFDataInS3Bucket(pdfData, s3Bucket, s3Prefix);
if (browser) await browser.close();
return s3ParamsToRetrievePDF;
} catch(error) {
if (browser) await browser.close();
throw error;
}
}
async function uploadPDFDataInS3Bucket(buffer, s3Bucket, s3Prefix) {
const Bucket = s3Bucket;
const Key = s3Prefix.concat('/', new Date().getTime().toString().concat(Math.random().toString(36).slice(2)), '.pdf');
const upload = new Upload({ client: s3, params: { Bucket, Key, Body: buffer } });
await upload.done();
return { Bucket, Key };
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment