节点调整图像大小并上传到AWS

时间:2015-04-01 14:58:46

标签: node.js amazon-web-services amazon-s3

我对节点比较陌生,想要编写一个从S3存储桶中获取图像的模块,调整它的大小并将其保存到亚马逊新Lambda服务的临时目录中,然后上传图像回到桶中。

当我运行代码时,似乎没有调用任何函数(downloadtransformupload)。我使用tmp创建临时目录,使用graphicsMagick来调整图像大小。

我的代码出了什么问题?

我已经在模块外部定义了依赖项和数组,因为我有另一个依赖于它们的数据。

// dependencies
var AWS = require('aws-sdk');
var gm = require('gm').subClass({ imageMagick: true });
var fs = require("fs");
var tmp = require("tmp");

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

var _800px = {
    width: 800,
    destinationPath: "large"
};

var _500px = {
    width: 500,
    destinationPath: "medium"
};

var _200px = {
    width: 200,
    destinationPath: "small"
};

var _45px = {
    width: 45,
    destinationPath: "thumbnail"
};

var _sizesArray = [_800px, _500px, _200px, _45px];

var len = _sizesArray.length;

exports.AwsHandler = function(event) {
    // Read options from the event.
    var srcBucket = event.Records[0].s3.bucket.name;
    var srcKey = event.Records[0].s3.object.key;
    var dstnKey = srcKey;

    // create temporary directory
    var tmpobj = tmp.dirSync();

    // function to determine paths
    function _filePath (directory, i) {
        if (!directory) {
            return "dst/" + _sizesArray[i].destinationPath + "/" + dstnKey;
        } else {
            return directory + "/dst/" + _sizesArray[i].destinationPath + "/" + dstnKey;
        }
    };


    // Infer the image type.
    var typeMatch = srcKey.match(/\.([^.]*)$/);
    if (!typeMatch) {
        console.error('unable to infer image type for key ' + srcKey);
        return;
    };

    var imageType = typeMatch[1];

    if (imageType != "jpg" && imageType != "png") {
        console.log('skipping non-image ' + srcKey);
        return;
    };


    (function resizeImage () {
        function download () {

            console.log("started!");

            s3.getObject({
                    Bucket: srcBucket,
                    Key: srcKey
                },
                function (err, response) {
                    if (err) {
                        console.error(err);
                    }
                    // call transform if successful
                    transform (response);
                }
            );
        };

        function transform (response) {

            for ( var i = 0; i<len; i++ ) {

                // define path for image write
                var _Key = _filePath (tmpobj, i);

                // resize images
                gm(response.Body, srcKey)
                    .resize(_sizesArray[i].width)
                    .write(_Key, function (err) {
                        if (err) {
                            console.error(err);
                        }
                        upLoad ();
                    });
            }
        };

        function upLoad () {

            for ( var i = 0; i<len; i++ ) {

                var readPath = _filePath (tmpobj, i);

                var writePath = _filePath (i);

                // read file from temp directory
                fs.readFile(readPath, function (err, data) {
                    if (err) {
                        console.error(err);
                    }

                    // upload images to s3 bucket
                    s3.putObject({
                        Bucket: srcBucket,
                        Key: writePath,
                        Body: data,
                        ContentType: data.type
                    },
                    function (err) {
                        if (err) {
                            console.error(err);
                        }
                        console.log("Uploaded with success!");
                    });
                })
            }
            // Manual cleanup of temporary directory
            tmpobj.removeCallback();
        };
    }());
};

1 个答案:

答案 0 :(得分:0)

以下是部分改进,请注意async库的使用。您将在upLoad()中遇到问题,因为您正在立即触发四个异步调用(在for循环中),并且没有简单的方法可以知道它们何时完成。 (好的,简单的方法是重写函数以使用异步库,如async.forEach)

// dependencies
var AWS = require('aws-sdk');
var gm = require('gm').subClass({ imageMagick: true });
var fs = require("fs");
var tmp = require("tmp");
var async = require("async");

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

var _800px = {
  width: 800,
  destinationPath: "large"
};

var _500px = {
  width: 500,
  destinationPath: "medium"
};

var _200px = {
  width: 200,
  destinationPath: "small"
};

var _45px = {
  width: 45,
  destinationPath: "thumbnail"
};

var _sizesArray = [_800px, _500px, _200px, _45px];

var len = _sizesArray.length;

exports.AwsHandler = function(event) {
  // Read options from the event.
  var srcBucket = event.Records[0].s3.bucket.name;
  var srcKey = event.Records[0].s3.object.key;
  var dstnKey = srcKey;

  // create temporary directory
  var tmpobj = tmp.dirSync();

  // function to determine paths
  function _filePath (directory, i) {
    if (!directory) {
      return "dst/" + _sizesArray[i].destinationPath + "/" + dstnKey;
    } else {
      return directory + "/dst/" + _sizesArray[i].destinationPath + "/" + dstnKey;
    }
  };


  // Infer the image type.
  var typeMatch = srcKey.match(/\.([^.]*)$/);
  if (!typeMatch) {
    console.error('unable to infer image type for key ' + srcKey);
    return;
  };

  var imageType = typeMatch[1];

  if (imageType != "jpg" && imageType != "png") {
    console.log('skipping non-image ' + srcKey);
    return;
  };


  // Actually call resizeImage, the main pipeline function:
  resizeImage(function(err){
    // Done. Manual cleanup of temporary directory
    tmpobj.removeCallback();
  })


  function resizeImage (callback) {
    var s3obj = {
      Bucket: srcBucket,
      Key: srcKey
    };
    download(s3obj, function(response){
      var gmConfigs = sizesArray.map(function(size, i){
        return {
          width: size.width
          _Key: _filePath (tmpobj, i)
        }
      })

      async.eachSeries(gmConfigs,
      function(config, done){
        transform(response, config.width, config._Key, done)
      },
      function(err){
        if(err){
          console.log(err);
        } else {
          upLoad();
          // Further work is required to identify if all the uploads worked,
          // and to know when to call callback() here
          // callback();
        }
      })
    })
  }

  function download (s3obj, callback) {
    console.log("started!");

    s3.getObject(s3obj, function (err, response) {
      if (err) {
        console.error(err);
      }
      // call transform if successful
      callback(response);
    });
  };

  function transform (response, width, _Key, callback) {
    // resize images
    gm(response.Body, srcKey)
    .resize(width)
    .write(_Key, function (err) {
      if (err) {
        console.error(err);
      }
      callback();
    });
  };

  function upLoad () {
    for ( var i = 0; i<len; i++ ) {
      var readPath = _filePath (tmpobj, i);
      var writePath = _filePath (i);
      // read file from temp directory
      fs.readFile(readPath, function (err, data) {
        if (err) {
          console.error(err);
        }

        // upload images to s3 bucket
        s3.putObject({
          Bucket: srcBucket,
          Key: writePath,
          Body: data,
          ContentType: data.type
        },
        function (err) {
          if (err) {
            console.error(err);
          }
          console.log("Uploaded with success!");
        });
      })
    }
  };

};