Convert PDF to Images using AWS Lambda with Nodejs

WARNING: It's not 100% perfect solution, it can NOT support huge file probably you can not handle file over than 500MB. If you found other better way please share with me :)

Create a AWS Lambda Function

Add AWS Layers

Create Project

$ mkdir pdf-to-images
$ cd pdf-to-images
$ npm init --yes
$ npm i pdf-lib gm aws-sdk
$ touch index.js

Code Snippet

const fs = require('fs').promises;
const AWS = require('aws-sdk');
const gm = require("gm").subClass({imageMagick: true});
const s3 = new AWS.S3();
const PDFDocument = require('pdf-lib').PDFDocument;
const convert = (body, index, bucket, dist) => {
return new Promise((resolve, reject) => {
console.log(`gm process started: page ${index}.`);
gm(body, `pdf.pdf[${index}]`)
.resize(1536)
.density(200)
.quality(80)
.setFormat('jpeg')
.stream((error, stdout, stderr) => {
if (error) {
console.log("gm conversion process error::1");
reject(error);
}
const chunks = [];
stdout.on('data', (chunk) => {
chunks.push(chunk);
});
stdout.on('end', () => {
console.log(`gm process complete: page ${index}.`);
const buffer = Buffer.concat(chunks);
s3.putObject({
Bucket: bucket,
Key: `${dist}/${index}.jpeg`,
ContentType: 'image/jpeg',
Body: buffer,
ACL: 'public-read',
}, (error, data) => {
if (error) {
console.log("gm conversion process error::2");
reject(error);
}
resolve();
});
});
stderr.on('data', (data) => {
console.log('stderr:', data);
});
});
});
}
async function handler(event, context, callback) {
try {
console.log('starting converting process...');
console.log('start downloaded PDF...');
const bucket = event.Records[0].s3.bucket.name;
const key = decodeURIComponent(event.Records[0].s3.object.key).replace(/\+/g, ' ');
const pdf = await s3.getObject({
Bucket: bucket,
Key: key,
}).promise();
console.log('converting PDF to images...');
const pdoc = await PDFDocument.load(pdf.Body);
const pageCount = pdoc.getPageCount() - 1;
const pages = Array.from({ length: pageCount }).map((_, i) => i);
for await(let page of pages) {
await convert(pdf.Body, page, bucket, key);
}
callback(null, {
statusCode: 200,
message: 'Success',
});
} catch (error) {
console.error(JSON.stringify(error));
callback(null, {
statusCode: 400,
message: 'Failed',
});
}
}
exports.handler = handler;

Conclusion

--

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Laravel 9 + Inertia.js + React + TypeScript

A Way to Set Local Storage on WKWebView

Best Practices For Using Comments In JavaScript

Sharing Types Between Backend and Frontend with the BFF Pattern

Three.js or There’s a hypercube in my timeline and I can’t get out

BEM Naming Convention

Large Format Charity Check Template

Providing Cross Domain access to images and data in Codepen

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
andyyou

andyyou

More from Medium

Going Serverless

Serverless on AWS:-

The Art of Building Lambda Apps

How to use TypeORM with serverless Aurora?