diff --git a/bin/jpegoptim.aws b/bin/jpegoptim.aws new file mode 100755 index 0000000..94eb573 Binary files /dev/null and b/bin/jpegoptim.aws differ diff --git a/context.json b/context.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/context.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/event.json b/event.json new file mode 100644 index 0000000..c7b0490 --- /dev/null +++ b/event.json @@ -0,0 +1,38 @@ +{ + "Records": [ + { + "eventVersion": "2.0", + "eventTime": "1970-01-01T00:00:00.000Z", + "requestParameters": { + "sourceIPAddress": "127.0.0.1" + }, + "s3": { + "configurationId": "testConfigRule", + "object": { + "eTag": "0123456789abcdef0123456789abcdef", + "sequencer": "0A1B2C3D4E5F678901", + "key": "foo/bar/3/e/f/e/3efed655ff1a21cb60bba97cd3c2296877fb8a5a.jpg", + "size": 1024 + }, + "bucket": { + "arn": "arn:aws:s3:::bucket", + "name": "bucket", + "ownerIdentity": { + "principalId": "EXAMPLE" + } + }, + "s3SchemaVersion": "1.0" + }, + "responseElements": { + "x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH", + "x-amz-request-id": "EXAMPLE123456789" + }, + "awsRegion": "eu-central-1", + "eventName": "ObjectCreated:Put", + "userIdentity": { + "principalId": "EXAMPLE" + }, + "eventSource": "aws:s3" + } + ] +} \ No newline at end of file diff --git a/lib/optim.js b/lib/optim.js index 3873e4c..ac7d2ff 100644 --- a/lib/optim.js +++ b/lib/optim.js @@ -1,7 +1,9 @@ var aws = require('aws-sdk'); var s3 = new aws.S3({ apiVersion: '2006-03-01' }); -var Imagemin = require('imagemin'); -var optipng = require('imagemin-optipng'); +var imagemin = require('imagemin'); +var imageminOptipng = require('imagemin-optipng'); +var imageminJpegoptim = require('imagemin-jpegoptim'); + var async = require('async'); var acl = process.env.UPLOAD_ACL || 'public-read'; @@ -9,14 +11,14 @@ var uploadBucket = process.env.UPLOAD_BUCKET; var pngLevel = +process.env.PNG_OPTIM_LEVEL || 7; var skipSize = +process.env.MAX_FILE_SIZE || -1; -exports.optim = function(event, context) { +exports.optim = function(event, context, callback) { var bucket = event.Records[0].s3.bucket.name; var key = event.Records[0].s3.object.key; - if(!/\.png$/.test(key)){ - console.log('Not a PNG'); - return setImmediate(function(){ context.done(); }); + if(!/\.png$/.test(key) && !/\.jpg$/.test(key)){ + console.log('Not a PNG or JPG'); + return setImmediate(function(){ callback(null, 'Not a PNG'); }); } key = require('querystring').parse('a=' + key).a; @@ -57,39 +59,55 @@ exports.optim = function(event, context) { }, function(meta, obj, cb){ - new Imagemin() - .src(obj.Body) - .use(optipng({ optimizationLevel: pngLevel })) - .run(function(err, files){ - if(err) return cb(err); - - console.log('Optimized! Final file size is ' + files[0].contents.length + ' bytes'); + var plugin + if(/\.png$/.test(key)){ + plugin = imageminOptipng({optimizationLevel: pngLevel}); + } else { + plugin = imageminJpegoptim({progressive: true}); + } - cb(null, meta, obj, files[0]) + imagemin.buffer(obj.Body, {use: [plugin]}).then(buf => { + console.log('Optimized! Final file size is ' + buf.length + ' bytes'); + cb(null, meta, obj, buf) + }).catch(err => { + callback(err) }); }, - function(meta, obj, file, cb){ - meta.Metadata.optimized = 'yes'; - - s3.putObject({ - ACL: acl, - Bucket: uploadBucket || bucket, - Key: key, - Body: file.contents, - ContentType: obj.ContentType, - Metadata: meta.Metadata - }, function(err){ - if(err) return cb(err); - - console.log('done!'); - cb(); - }); + function(meta, obj, body, cb){ + var oriSize = obj.Body.length + var newSize = body.length + var percent = Math.round(((oriSize - newSize) / oriSize) * 10000) / 100; + console.log('File ' + key + ' was optimzed from ' + oriSize + ' bytes to ' + newSize + ' bytes. ' + percent + '%.') + + if (newSize < oriSize) { + meta.Metadata.optimized = 'yes'; + + s3.putObject({ + ACL: acl, + Bucket: uploadBucket || bucket, + Key: key, + Body: body, + ContentType: obj.ContentType, + Metadata: meta.Metadata, + StorageClass: meta.StorageClass + }, function (err) { + if (err) return cb(err); + + console.log('done!'); + callback(null, 'File was optimzed from ' + oriSize + ' bytes to ' + newSize + ' bytes. ' + percent + '%.') + }); + } else { + console.log("Optimized file was not smaller than original file. Not uploading.") + callback(null, "Optimized file was not smaller than original file. Not uploading.") + } } ], function(err){ if(err === 'skip'){ err = null; } - context.done(err); + callback(err); + console.log(err); + //context.done(err); }); }; diff --git a/package.json b/package.json index b69ad40..d378280 100644 --- a/package.json +++ b/package.json @@ -14,10 +14,11 @@ }, "dependencies": { "async": "^1.5.0", - "imagemin": "^3.2.0", - "imagemin-optipng": "^4.3.0" + "imagemin": "^5.2.0", + "imagemin-optipng": "^5.1.0", + "imagemin-jpegoptim": "^5.0.0" }, "devDependencies": { - "node-lambda": "^0.7.1" + "node-lambda": "^0.8.6" } } diff --git a/post_install.sh b/post_install.sh new file mode 100755 index 0000000..19b9f7c --- /dev/null +++ b/post_install.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +# for aws lambda, we need a different jpegoptim than produced on ubuntu +cp bin/jpegoptim.aws node_modules/jpegoptim-bin/vendor/jpegoptim \ No newline at end of file