5

I have been trying to create a AWS node lambda function to download a PDF file from S3, generate a thumbnail for the first page of that file, and upload that thumbnail back to S3. Since I am no expert I tried inspiring myself from the Lambda example provide by AWS to resize images as well as a node.js found on SO of a PDF thumbnail generator in node.js but have not been able to make it work. The download from S3 works, the upload back to S3 works, but the thumbnail generation fails. See my code below:

// Download the pdf from S3, create thumbnail, and upload to cache.
	async.waterfall([
		function download(next) {
			// Download the pdf from S3 into a buffer.
			s3.getObject({
					Bucket: BUCKET,
					Key: pdfkey
				},
				next);
			},
		function thumbnail(response, next) {
			gm(response.Body[0]).size(function(err, size) {
				// Transform the image buffer in memory.
				this.resize(requestedwidth, requestedheight).toBuffer(format.toUpperCase(), function(err, buffer) {
					if (err) {
						console.log('failed generating thumbnail');
						next(err);
					} else {
						next(null, response.ContentType, buffer);
					}
				});
			});
		},
		function upload(contentType, data, next) {
			// Stream the thumbnail
			s3.putObject({
					Bucket: BUCKET,
					Key: thumbnailkey,
					ACL:"public-read",
					Body: data,
					ContentType: contentType
				},
				next);
			}
		], function (err) {
			if (err) {
				context.fail(new Error(
					'Unable to create thumbnail for ' + BUCKET + '/' + pdfkey +
					' and upload to ' + BUCKET + '/' + thumbnailkey +
					' due to an error: ' + err
				));
			} else {
				context.succeed(
					'Successfully resized ' + BUCKET + '/' + pdfkey +
					' and uploaded to ' + BUCKET + '/' + thumbnailkey
				);
			}
		}
	);

Any help would be greatly appreciated!

1
  • Did you ever get this figured out? Looking to do the same thing. Cheers Commented May 25, 2016 at 19:11

1 Answer 1

5

Here is the code that ended up working. Code below with the following 4 libs in node modules:

  • async
  • gm
  • mktemp
  • pdf-image

:

var async = require('async');
var AWS = require('aws-sdk');
var gm = require('gm').subClass({ imageMagick: true }); // Enable ImageMagick integration. 
var util = require('util');
var fs = require('fs');
var mktemp = require("mktemp");

var BUCKET  = "XXXXXXXXXX";

var s3 = new AWS.S3();
exports.handler = function(event, context) {

var pdfkey = decodeURIComponent(event.pdfkey.replace(/\+/g, " ")); 
var thumbnailkey = decodeURIComponent(event.thumbnailkey.replace(/\+/g, " ")); 
var requestedwidth = event.width;
var requestedheight = event.height;
var shape = event.shape;
var format = event.format;

// Infer the pdf type.
var typeMatch = pdfkey.match(/\.([^.]*)$/);
if (!typeMatch) {
    context.fail(new Error('unable to infer pdf type for key ' + pdfkey));
    return;
}
var fileType = typeMatch[1];
if (fileType != "pdf") {
    context.fail(new Error('skipping non-pdf ' + pdfkey));
    return;
}

// Download the pdf from S3, create thumbnail, and upload to cache.
async.waterfall([
    function download(next) {
        // Download the pdf from S3 into a buffer.
        s3.getObject({
            Bucket: BUCKET,
            Key: pdfkey
        },
        next);
    },
    function thumbnail(response, next) {
        console.log('generating thumbnail');
        var temp_file, image;

        temp_file = mktemp.createFileSync("/tmp/XXXXXXXXXX.pdf");
        fs.writeFileSync(temp_file, response.Body);
        image = gm(temp_file + "[0]").flatten().colorspace("CMYK");

        image.size(function(err, size) {
            if ((requestedwidth > 0) && (requestedheight > 0))
            {

                if (shape == "pad")
                {
                    // Transform the image buffer in memory.
                    this.resize(requestedwidth, requestedheight).gravity('Center').background('transparent').extent(requestedwidth, requestedheight)
                    .toBuffer(format.toUpperCase(), function(err, buffer) {
                        if (err) {
                            next(err);
                        } else {
                            next(null, response.ContentType, buffer);
                        }
                    });
                }
                else
                {
                    // Transform the image buffer in memory.
                    this.resize(requestedwidth, requestedheight)
                    .toBuffer(format.toUpperCase(), function(err, buffer) {
                        if (err) {
                            next(err);
                        } else {
                            next(null, response.ContentType, buffer);
                        }
                    });
                }
            }
            else
            {
                if (requestedwidth > 0)
                {
                    // Transform the image buffer in memory.
                    this.resize(requestedwidth)
                    .toBuffer(format.toUpperCase(), function(err, buffer) {
                        if (err) {
                            next(err);
                        } else {
                            next(null, response.ContentType, buffer);
                        }
                    });

                }
                else
                {
                    // Transform the image buffer in memory.
                    this.resize(null, requestedheight)
                    .toBuffer(format.toUpperCase(), function(err, buffer) {
                        if (err) {
                            next(err);
                        } else {
                            next(null, response.ContentType, buffer);
                        }
                    });
                }
            }
        });
    },
    function upload(contentType, data, next) {
        // Stream the thumbnail
        console.log('uploading thumbnail');
        s3.putObject({
            Bucket: BUCKET,
            Key: thumbnailkey,
            ACL:"public-read",
            Body: data,
            ContentType: "image/" + format
        },
        next);
    }
    ], function (err) {
        if (err) {
            context.fail(new Error(
                'Unable to create thumbnail for ' + BUCKET + '/' + pdfkey +
                ' and upload to ' + BUCKET + '/' + thumbnailkey +
                ' due to an error: ' + err
                ));
        } else {
            context.succeed(
                'Successfully resized ' + BUCKET + '/' + pdfkey +
                ' and uploaded to ' + BUCKET + '/' + thumbnailkey
                );
        }
    }
    );
};
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.