当我尝试发送大图像时,我在Lambda中遇到了这个代码的问题。 我发送了一堆图像,并调整大小并创建了几个不同的大小,如数组SIZES所示。
我的Lambda配置处于高位,最大内存(1536mb)和最大超时5mim 。
当大图像上传时出现问题。我搜索了所有互联网,但我找不到解决方案。
错误
Unhandled rejection Error: Stream yields empty buffer
at Socket.<anonymous> (/var/task/node_modules/gm/lib/command.js:57:17)
at emitNone (events.js:72:20)
at Socket.emit (events.js:166:7)
at endReadableNT (_stream_readable.js:905:12)
at nextTickCallbackWith2Args (node.js:437:9)
at process._tickDomainCallback (node.js:392:17)
**这是代码。*
var gm = require('gm').subClass({
imageMagick: true
}),
aws = require('aws-sdk'),
async = require('async'),
fs = require('fs'),
promise = require('bluebird'),
request = require('request').defaults({
encoding: null
});
var BUCKET = "myBucket",
FOLDER = 'photos/',
s3 = new aws.S3({
accessKeyId: 'myKeyId',
secretAccessKey: 'mySecretKey'
}),
SIZES = [{
type: 'original',size: 1080,mark: false,hide: true
}, {
type: 'thumb',size: 120, mark: false, hide: false
}, {
type: 'thumb',size: 240, mark: false, hide: false
}, {
type: 'thumb',size: 360, mark: false, hide: false
}, {
type: 'card',size: 350 ,mark: false, hide: false
}, {
type: 'full',size: 360, mark: true, hide: false
}, {
type: 'full',size: 540, mark: true, hide: false
}, {
type: 'full',size: 720, mark: true, hide: false
}, {
type: 'full',size: 900, mark: true, ide: false
}, {
type: 'full',size: 1080, mark: true, hide: false
}];
var service = {
s3: {
download: function(bucket, key) {
return new promise(function(resolve, reject) {
s3.getObject({
Bucket: bucket,
Key: key
}, function(err, data) {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
},
upload: {
async: function(photo, bucket, key, content_type, private) {
return new promise(function(resolve, reject) {
s3.putObject({
Bucket: bucket,
Key: key,
Body: photo,
ContentType: content_type,
ACL: private ? 'private' : 'public-read'
}, function(err, data) {
if (err) {
reject(err)
} else {
resolve(key);
}
});
});
}
}
},
watermark: {
resize: function(photo, name) {
var temp = '/tmp/w_' + name + '.png';
return new promise(function(resolve, reject) {
gm(photo).size(function(err, size) {
var that = this;
if (err) {
reject(err);
}
var smaller = size.width > size.height ? size.height : size.width;
var _size = smaller * 0.8;
request.get('https://s3.amazonaws.com/FOLDER/photos/watermark.png', function(e, r, body) {
gm(body)
.resize(_size)
.write(temp, function(error) {
if (error) reject(error);
that.composite(temp)
.gravity('Center')
.toBuffer(function(e, buffer) {
if (e) reject(e);
fs.access(temp, fs.F_OK, function(err) {
if (!err) {
fs.unlinkSync(temp);
}
});
resolve(buffer);
});
});
});
});
});
}
},
resize: function(photo, width, height) {
return new promise(function(resolve, reject) {
gm(photo).resize(width, height).toBuffer(function(err, buffer) {
if (err) {
reject(err);
}
resolve(buffer);
});
});
},
crop: function(photo, width, height) {
return new promise(function(resolve, reject) {
gm(photo).size(function(err, size) {
if (err) {
reject(err);
}
var x = 0,
y = 0;
if (size.width > size.height) {
this.resize(null, height);
x = (((height * size.width) / size.height) - width) / 2;
} else {
this.resize(width);
y = (((width * size.height) / size.width) - height) / 2;
}
this.crop(width, height, x, y).toBuffer(function(err, buffer) {
resolve(buffer);
});
});
});
},
process: function(type, photo, width, height) {
if (type == 'thumb') {
return service.crop(photo, width, height);
} else {
return service.resize(photo, width, height);
}
}
};
exports.handler = function(event, context, callback) {
var $filename = event.filename,
$session = event.session,
$mimetype = null,
$original = null,
$watermarked = null;
async.waterfall([
function(_next) {
service.s3.download(BUCKET, FOLDER + $session + '/original/' + $filename).then(function(_original) {
$mimetype = _original.ContentType;
$original = _original.Body;
_next(null);
}, function(_error) {
_next(_error);
});
},
function(_next) {
service.watermark.resize($original, (Math.random().toString(36).slice(-6) + new Date().getTime())).then(function(_watermarked) {
$watermarked = _watermarked;
_next(null);
});
},
function(_next) {
async.each(SIZES, function(_image, _callback) {
service.process(_image.type, _image.mark ? $watermarked : $original, _image.size, _image.size).then(function(_generated) {
service.s3.upload.async(_generated, BUCKET, FOLDER + $session + '/' + _image.type + '/' + (_image.type != 'card' ? _image.size + '_' : '') + $filename, $mimetype, _image.hide).then(function() {
_callback(null);
});
});
}, function() {
_next(null);
});
}
], function() {
callback(null, 'Imagens processadas. Session: ' + $session);
});
};
答案 0 :(得分:1)
旧程序需要很长时间才能完成,然后lambda会耗尽内存。
我解决了这个问题,在两个大小中打破了数组。然后使用async.each将函数复制到新数组。
这种新方法可以完美运行并创建所有图像。
答案 1 :(得分:0)
之前我遇到过这个错误,并最终追踪它以达到内存限制。幸运的是,我能够增加记忆的大小,这解决了问题。
不幸的是,我发现你已经处于最大允许内存并且仍然达到了极限。这些图片的上传量有多大?如果它们确实很大,并且您需要将输出作为一个图像,那么我可以看到如何做到的唯一方法就是上传巨大的图像文件,将其裁剪成x4或更小的图像,调整每个图像和然后再将每个人重新组合在一起。