Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AWS Lambda gives error on putting s3 object

I am working on a function which creates a thumbnail by saving a thumbnail version of the image in the screenshot folder when any image is uploaded to the images folder in the bucket. I am using serverless framework. I keep getting an error shown below. I have pasted exact code so anyone can copy paste and implement this solution. Serverless.yml, handler function file as well as any supporting file is included as well.

I can't figure out when i am referring to buffer why do i get this error that object type is not buffer etc.

 { InvalidParameterType: Expected params.Body to be a string, Buffer, Stream, Blob, or typed array object
at ParamValidator.fail (/var/runtime/node_modules/aws-sdk/lib/param_validator.js:50:37)
at ParamValidator.validatePayload (/var/runtime/node_modules/aws-sdk/lib/param_validator.js:255:10)
at ParamValidator.validateScalar (/var/runtime/node_modules/aws-sdk/lib/param_validator.js:133:21)
at ParamValidator.validateMember (/var/runtime/node_modules/aws-sdk/lib/param_validator.js:94:21)
at ParamValidator.validateStructure (/var/runtime/node_modules/aws-sdk/lib/param_validator.js:75:14)
at ParamValidator.validateMember (/var/runtime/node_modules/aws-sdk/lib/param_validator.js:88:21)
at ParamValidator.validate (/var/runtime/node_modules/aws-sdk/lib/param_validator.js:34:10)
at Request.VALIDATE_PARAMETERS (/var/runtime/node_modules/aws-sdk/lib/event_listeners.js:125:42)
at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:105:20)
at callNextListener (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:95:12)
message: 'Expected params.Body to be a string, Buffer, Stream, Blob, or typed array object',
code: 'InvalidParameterType',
time: 2019-03-12T16:37:26.910Z }

Code:

Handler.js

'use strict';

const resizer = require('./resizer');

module.exports.resizer = (event, context, callback) => {
	console.log(event.Records[0].s3);

	const bucket = event.Records[0].s3.bucket.name;
	const key = event.Records[0].s3.object.key;

	console.log(`A file named ${key} was put in a bucket ${bucket}`);

	resizer(bucket, key)
		.then(() => {
			console.log(`The thumbnail was created`);
			callback(null, {
				message: 'The thumbnail was created'
			});
		})
		.catch(error => {
			console.log(error);
			callback(error);
		});
};

module.exports.thumbnails = (event, context, callback) => {
	const bucket = event.Records[0].s3.bucket.name;
	const key = event.Records[0].s3.object.key;

	console.log(bucket);
	console.log(key);

	console.log(`A new file ${key} was created in the bucket ${bucket}`);
	callback(null, {
		message: `A new file ${key} was created in the bucket ${bucket}`
	});
};

Resizer.js

'use strict';

const AWS = require('aws-sdk');
const S3 = new AWS.S3();
const Jimp = require('jimp'); //https://github.com/oliver-moran/jimp

module.exports = (bucket, key) => {
	const newKey = replacePrefix(key);
	const height = 512;

	return getS3Object(bucket, key).then(data => resizer(data.Body, height)).then(buffer => putS3Object(bucket, newKey, buffer));
};

function getS3Object(bucket, key) {
	return S3.getObject({
		Bucket: bucket,
		Key: key
	}).promise();
}

function putS3Object(bucket, key, body) {
	return S3.putObject({
		Body: body,
		Bucket: bucket,
		ContentType: 'image/jpg',
		Key: key
	}).promise();
}

function replacePrefix(key) {
	const uploadPrefix = 'uploads/';
	const thumbnailsPrefix = 'thumbnails/';
	return key.replace(uploadPrefix, thumbnailsPrefix);
}

function resizer(data, height) {
	return Jimp.read(data)
		.then(image => {
			return image
				.resize(Jimp.AUTO, height)
				.quality(100) // set JPEG quality
				.getBuffer(Jimp.MIME_JPEG, (err, buffer) => {
					return buffer;
				});
		})
		.catch(err => err);
}

Serverless.yml

service: serverless-resizer-project # NOTE: update this with your service name


provider:
  name: aws
  runtime: nodejs6.10
  profile: student1

  iamRoleStatements:
    - Effect: "Allow"
      Action:
        - "s3:ListBucket"
        - "s3:GetObject"
        - "s3:PutObject"
      Resource: "arn:aws:s3:::serverless-resizer-project-images/*"

functions:
  resizer:
    handler: handler.resizer
    events:
      - s3:
          bucket: serverless-resizer-project-images
          event: s3:ObjectCreated:*
          rules:
            - prefix: uploads/
            - suffix: .jpg
	thumbnails:
    handler: handler.thumbnails
    events:
      - s3:
          bucket: serverless-resizer-project-images
          event: s3:ObjectCreated:*
          rules:
            - prefix: thumbnails/
            - suffix: .jpg					
like image 655
Asad Feroz Ali Avatar asked Aug 31 '26 16:08

Asad Feroz Ali


1 Answers

The return value of your resizer function is not what you expect. You're using the getBuffer function with a callback, which means that the buffer of the image is not resolved by the promise, but instead is used in the callback, which is not your intention. You should instead use getBufferAsync, which returns a promise that resolves to the image buffer. Your resizer function should look something like this:

function resizer(data, height) {
    return Jimp.read(data)
        .then(image => image
                .resize(Jimp.AUTO, height)
                .quality(100) // set JPEG quality
                .getBufferAsync(Jimp.MIME_JPEG)
        )
        .catch(err => err);
}
like image 181
Kalev Avatar answered Sep 03 '26 08:09

Kalev



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!