TypeError: Cannot read property 'width' of undefined gm library

TypeError: Cannot read property 'width' of undefined gm library

之前,我曾按照 link 使用 AWS Lambda 成功创建缩略图。节点版本为 8.10.

现在,由于 AWS 将弃用任何具有此节点版本的应用程序,我必须将节点版本更新为 10.x.

We are contacting you as we have identified that your AWS Account currently has one or more Lambda functions using Node.js 8.10, which will reach its EOL at the end of 2019.

What’s happening?

The Node community has decided to end support for Node.js 8.x on December 31, 2019 1. From this date forward, Node.js 8.x will stop receiving bug fixes, security updates, and/or performance improvements. To ensure that your new and existing functions run on a supported and secure runtime, language runtimes that have reached their EOL are deprecated in AWS 2.

For Node.js 8.x, there will be 2 stages to the runtime deprecation process:

  1. Disable Function Create – Beginning January 6, 2020, customers will no longer be able to create functions using Node.js 8.10

  2. Disable Function Update – Beginning February 3, 2020, customers will no longer be able to update functions using Node.js 8.10

After this period, both function creation and updates will be disabled permanently. However, existing Node 8.x functions will still be available to process invocation events.

What do I need to do?

We encourage you to update all of your Node.js 8.10 functions to the newer available runtime version, Node.js 10.x[3]. You should test your functions for compatibility with the Node.js 10.x language version before applying changes to your production functions.

What if I have issues/What if I need help?

Please contact us through AWS Support [4] or the AWS Developer Forums [5] should you have any questions or concerns.

因此,我已将我的节点版本更新为 10.17.0 并在 AWS Lambda 中再次部署该程序包。现在,如果任何图像已上传到 S3 并且 aws lambda 尝试将图像转换为缩略图,它会显示以下错误:

这是完整代码:

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

// constants
var MAX_WIDTH  = 100;
var MAX_HEIGHT = 100;

// get reference to S3 client 
var s3 = new AWS.S3();

exports.handler = function(event, context, callback) {
    // Read options from the event.
    console.log("Reading options from event:\n", util.inspect(event, {depth: 5}));
    var srcBucket = event.Records[0].s3.bucket.name;
    // Object key may have spaces or unicode non-ASCII characters.
    var srcKey    =
    decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " "));  
    var dstBucket = srcBucket + "resized";
    var dstKey    = "resized-" + srcKey;

    // Sanity check: validate that source and destination are different buckets.
    if (srcBucket == dstBucket) {
        callback("Source and destination buckets are the same.");
        return;
    }

    // Infer the image type.
    var typeMatch = srcKey.match(/\.([^.]*)$/);
    if (!typeMatch) {
        callback("Could not determine the image type.");
        return;
    }
    var imageType = typeMatch[1].toLowerCase();
    if (imageType != "jpg" && imageType != "png") {
        callback(`Unsupported image type: ${imageType}`);
        return;
    }

    // Download the image from S3, transform, and upload to a different S3 bucket.
    async.waterfall([
        function download(next) {
            // Download the image from S3 into a buffer.
            s3.getObject({
                    Bucket: srcBucket,
                    Key: srcKey
                },
                next);
            },
        function transform(response, next) {
            gm(response.Body).size(function(err, size) {
                // Infer the scaling factor to avoid stretching the image unnaturally.
                var scalingFactor = Math.min(
                    MAX_WIDTH / size.width,
                    MAX_HEIGHT / size.height
                );
                var width  = scalingFactor * size.width;
                var height = scalingFactor * size.height;

                // Transform the image buffer in memory.
                this.resize(width, height)
                    .toBuffer(imageType, function(err, buffer) {
                        if (err) {
                            next(err);
                        } else {
                            next(null, response.ContentType, buffer);
                        }
                    });
            });
        },
        function upload(contentType, data, next) {
            // Stream the transformed image to a different S3 bucket.
            s3.putObject({
                    Bucket: dstBucket,
                    Key: dstKey,
                    Body: data,
                    ContentType: contentType
                },
                next);
            }
        ], function (err) {
            if (err) {
                console.error(
                    'Unable to resize ' + srcBucket + '/' + srcKey +
                    ' and upload to ' + dstBucket + '/' + dstKey +
                    ' due to an error: ' + err
                );
            } else {
                console.log(
                    'Successfully resized ' + srcBucket + '/' + srcKey +
                    ' and uploaded to ' + dstBucket + '/' + dstKey
                );
            }

            callback(null, "message");
        }
    );
};

错误基本上在这一行:

gm(response.Body).size(function(err, size) {
                // Infer the scaling factor to avoid stretching the image unnaturally.
                var scalingFactor = Math.min(
                    MAX_WIDTH / size.width, // In this line where the size is undefined
                    MAX_HEIGHT / size.height
                );

node版本8.10运行完美。我不知道在这种情况下该怎么做。我在配置1024MB内存大小

谁能指出我应该更改哪里?提前致谢。

问题是,NodeJS 不再支持 gm 10.x:https://github.com/aheckmann/gm/issues/752

所以这里会有问题。似乎您必须创建并使用 Lambda 层来修复它。但真正的问题出现了,如果你使用的是 Lambda@Edge,因为这里不允许使用 Lambda 层:https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-requirements-limits.html