[英]Upload generated PNG to amazon S3 from node on lambda
我正在從各自的 URL 下載 2 張 png 圖像,然后使用pixelmatch比較它們並生成第三張圖像。
然后我嘗試將第三張圖片上傳到 S3 存儲桶,但我很吃力。 代碼如下。
promise1
和promise2
分別是獲取png1
和png2
的兩個調用。 下面使用的dimensions1
數組是在promise1
中創建的。 PNG
是pngjs package。
const promArr = [promise1, promise2];
Promise.all(promArr).then(() => {
const diff = new PNG({ width: dimensions1[0], height: dimensions1[1] });
const pix = pixelmatch(png1.data, png2.data, diff.data, dimensions1[0], dimensions1[1], { threshold: 0.1 });
const size = dimensions1[0] * dimensions1[1];
diff.pack().pipe(fs.createWriteStream(`/tmp/${targetHash}.png`));
const percentage = ((pix / size) * 100);
const fileBuffer = fs.readFileSync(`/tmp/${targetHash}.png`);
const s3 = new AWS.S3();
s3.putObject({
ACL: 'public-read',
Key: targetFilename,
Body: fileBuffer,
Bucket: targetBucket,
ContentType: 'image/png',
}, (err) => {
if (err) {
console.warn(err);
cb(err);
} else {
cb(null, {
percentage,
hash: `${targetFilename}`,
key: `${targetFilename}`,
bucket: targetBucket,
url: `${event.stageVariables.endpoint}${targetFilename}`,
});
}
return;
});
})
.catch((err) => {
console.warn(`error: ${err}`);
cb(err);
});
這會將 URL 返回到在 mac 上預覽報告為空的圖像。 這向我表明我有一個異步問題。
我還嘗試將diff.pack()
作為正文傳遞並收到錯誤: Cannot determine length of [object Object]
。 我在這里找到了關於此錯誤的討論。
我覺得真的很接近解決方案,但我還沒有完全到達那里。 誰能幫忙? 謝謝
您可以將 stream 轉換為本文中提到的緩沖區。
如果您使用的是node >= 17.5.0
:
const streamToBuffer = (stream) => Buffer.concat(await stream.toArray());
如果您使用的是node < 17.5.0
:
const streamToBuffer = (stream) =>
new Promise((resolve, reject) => {
const chunks = [];
stream.on("data", (chunk) => chunks.push(chunk));
stream.once("end", () => resolve(Buffer.concat(chunks)));
stream.once("error", reject);
});
然后在你的代碼中實現它:
const width = dimensions1[0];
const height = dimensions1[1];
const diff = new PNG({ width, height });
pixelmatch(
png1.data,
png2.data,
diff.data,
width,
height,
{ threshold: 0.1 }
);
const diffBuffer = await streamToBuffer(diff.pack());
await s3Client
.send(
new PutObjectCommand({
Bucket: /* Bucket */,
Key: /* Key */,
Body: diffBuffer,
ContentType: "image/png",
})
)
請參閱下面的解決方案。 這是一個異步問題。 從這里拿筆記。 一旦用於創建臨時文件的管道完成,s3內容即會啟動。 注意這里提到的createReadStream的使用。
const promArr = [promise1, promise2];
Promise.all(promArr).then(() => {
const diff = new PNG({ width: dimensions1[0], height: dimensions1[1] });
const pix = pixelmatch(png1.data, png2.data, diff.data, dimensions1[0], dimensions1[1], { threshold: 0.1 });
const size = dimensions1[0] * dimensions1[1];
const percentage = ((pix / size) * 100);
diff.pack().pipe(fs.createWriteStream(`/tmp/${targetHash}.png`).on('finish', () => {
const fileBuffer = fs.createReadStream(`/tmp/${targetHash}.png`);
const s3 = new AWS.S3();
s3.putObject({
ACL: 'public-read',
Key: targetFilename,
Body: fileBuffer,
Bucket: targetBucket,
ContentType: 'image/png',
}, (err) => {
if (err) {
console.warn(err);
cb(err);
} else {
cb(null, {
percentage,
hash: `${targetFilename}`,
key: `${targetFilename}`,
bucket: targetBucket,
url: `${event.stageVariables.endpoint}${targetFilename}`,
});
}
return;
});
}));
})
.catch((err) => {
console.warn(`error: ${err}`);
cb(err);
});
我對寫給tmp然后再讀一遍並不完全滿意,但這似乎是目前解決aws-sdk限制的最簡單方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.