簡體   English   中英

將生成的 PNG 從 lambda 上的節點上傳到 amazon S3

[英]Upload generated PNG to amazon S3 from node on lambda

我正在從各自的 URL 下載 2 張 png 圖像,然后使用pixelmatch比較它們並生成第三張圖像。

然后我嘗試將第三張圖片上傳到 S3 存儲桶,但我很吃力。 代碼如下。

promise1promise2分別是獲取png1png2的兩個調用。 下面使用的dimensions1數組是在promise1中創建的。 PNGpngjs 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM