Node.js脚本工作一次,然后失败

我需要一个Node.js脚本,它执行以下操作:

1 – 将图像添加到指定的S3存储桶时触发。
2 – 创build该图像的缩略图(360×203像素)。
3 – 将该缩略图的副本保存在单独的S3文件夹内。
4 – 使用“FILENAME-X”命名约定,将缩略图上传到指定的FTP服务器,六(6)次。

代码的工作起初和预期一样。 示例事件拉取图像。 创build一个thumnail。 保存到另一个S3存储桶。 然后将其上传到FTP服务器。

问题:一次对testing文件HappyFace.jpg有效,但后续testing失败。 另外,我试着用不同的文件做,但不成功。

另外:如果我可以得到一些帮助编写一个循环来命名上传的不同文件,将非常感激。 我通常使用PHP编写代码,所以它可能比我希望写的更长。

注:我删除了我的FTP凭据隐私。

问题代码片段:

function upload(contentType, data, next) { // Upload test file to FTP server c.append(data, 'testing.jpg', function(err) { console.log("CONNECTION SUCCESS!"); if (err) throw err; c.end(); }); // Connect to ftp c.connect({ host: "", port: 21, // defaults to 21 user: "", // defaults to "anonymous" password: "" // defaults to "@anonymous" }); // S3 Bucket Upload Function Goes Here } 

完整代码:

 // dependencies var async = require('async'); var AWS = require('aws-sdk'); var util = require('util'); var Client = require('ftp'); var fs = require('fs'); var gm = require('gm') .subClass({ imageMagick: true }); // Enable ImageMagick integration. // get reference to FTP client var c = new Client(); // get reference to S3 client var s3 = new AWS.S3(); exports.handler = function(event, context) { // Read options from the event. console.log("Reading options from event:\n", util.inspect(event, {depth: 5})); // Get source bucket var srcBucket = event.Records[0].s3.bucket.name; // Get source object key // Object key may have spaces or unicode non-ASCII characters. var srcKey = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " ")); var url = 'http://' + srcBucket + ".s3.amazonaws.com/" + srcKey; // Set destination bucket var dstBucket = srcBucket + "-thumbs"; // Set destination object key var dstKey = "resized-" + srcKey; // 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; } // 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) { // Transform the image buffer in memory. this.toBuffer(imageType, function(err, buffer) { if (err) { next(err); } else { next(null, response.ContentType, buffer); } }); }); }, function upload(contentType, data, next) { // Upload test file to FTP server c.append(data, 'testing.jpg', function(err) { console.log("CONNECTION SUCCESS!"); if (err) throw err; c.end(); }); // Connect to ftp c.connect({ host: "", port: 21, // defaults to 21 user: "", // defaults to "anonymous" password: "" // defaults to "@anonymous" }); // Stream the thumb 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 ); } // context.done(); } ); }; 

日志:

 START RequestId: edc808c1-712b-11e5-aa8a-ed7c188ee86c Version: $LATEST 2015-10-12T21:55:20.481Z edc808c1-712b-11e5-aa8a-ed7c188ee86c Reading options from event: { 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: 'HappyFace.jpg', size: 1024 }, bucket: { arn: 'arn:aws:s3:::images', name: 'images', ownerIdentity: { principalId: 'EXAMPLE' } }, s3SchemaVersion: '1.0' }, responseElements: { 'x-amz-id-2': 'EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH', 'x-amz-request-id': 'EXAMPLE123456789' }, awsRegion: 'us-east-1', eventName: 'ObjectCreated:Put', userIdentity: { principalId: 'EXAMPLE' }, eventSource: 'aws:s3' } ] } 2015-10-12T21:55:22.411Z edc808c1-712b-11e5-aa8a-ed7c188ee86c Successfully resized images/HappyFace.jpg and uploaded to images-thumbs/resized-HappyFace.jpg 2015-10-12T21:55:23.432Z edc808c1-712b-11e5-aa8a-ed7c188ee86c CONNECTION SUCCESS! END RequestId: edc808c1-712b-11e5-aa8a-ed7c188ee86c REPORT RequestId: edc808c1-712b-11e5-aa8a-ed7c188ee86c Duration: 3003.76 ms Billed Duration: 3000 ms Memory Size: 128 MB Max Memory Used: 43 MB Task timed out after 3.00 seconds START RequestId: d347e7e3-712d-11e5-bfdf-05baa36d50fd Version: $LATEST 2015-10-12T22:08:55.910Z d347e7e3-712d-11e5-bfdf-05baa36d50fd Reading options from event: { 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: 'HappyFace.jpg', size: 1024 }, bucket: { arn: 'arn:aws:s3:::images', name: 'images', ownerIdentity: { principalId: 'EXAMPLE' } }, s3SchemaVersion: '1.0' }, responseElements: { 'x-amz-id-2': 'EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH', 'x-amz-request-id': 'EXAMPLE123456789' }, awsRegion: 'us-east-1', eventName: 'ObjectCreated:Put', userIdentity: { principalId: 'EXAMPLE' }, eventSource: 'aws:s3' } ] } END RequestId: d347e7e3-712d-11e5-bfdf-05baa36d50fd REPORT RequestId: d347e7e3-712d-11e5-bfdf-05baa36d50fd Duration: 3003.33 ms Billed Duration: 3000 ms Memory Size: 128 MB Max Memory Used: 17 MB Task timed out after 3.00 seconds 

该行:

 var c = new Client(); 

只会执行一次; 所有对你的handler()函数的调用都将使用你的FTP客户端的同一个实例。

如果可能有多个对handler()重叠调用,并且在一个asynchronous的世界中它肯定有可能,那么包括c.connect(…)c.end()在内的对FTP客户端的调用将被调用多次同一个 FTP客户端,可能已经有一个上传正在进行,导致这样的情况:

  1. 调用handler() 。 开始上传。
  2. 调用handler() 。 第二次上传开始。
  3. 首先上传完成并调用c.end()
  4. 第二次上传被取消。

解决方法是为每次上传创build一个新的FTP客户端实例,或者,如果您的FTP服务器有问题(限制客户端连接的数量),则需要以某种方式序列化您的上传。 一种方法做到这一点,因为你正在使用async库,将使用async.queue