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
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With