Невозможно загрузить изображение на s3, используя безсерверный фреймворк, но оно работает в автономном режиме (проблема с буфером) - PullRequest
1 голос
/ 23 февраля 2020

Я пытаюсь развернуть лямбда-функцию, позволяющую загрузить изображение на S3. Лямбда хорошо работает в автономном режиме, но при развертывании ее на AWS функция не работает.

Первая ошибка, с которой я столкнулся, была такая:

ERROR   (node:7) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.

Итак Я следовал рекомендации использовать вместо этого метод Buffer.from (). Но это тоже не работает. Лямбда работает до истечения времени ожидания.

Может кто-нибудь сказать мне, где я был не прав или предложить мне другое решение?

Ниже моей лямбда-функции:

const AWS = require("aws-sdk");
const Busboy = require("busboy");
const uuidv4 = require("uuid/v4");
require("dotenv").config();

AWS.config.update({
  accessKeyId: process.env.ACCESS_KEY_ID,
  secretAccessKey: process.env.SECRET_ACCESS_KEY,
  subregion: process.env.SUB_REGION
});

const s3 = new AWS.S3();

const getContentType = event => {
  // see the second block of codes
};

const parser = event => {
  // see the third block of codes
};


module.exports.main = (event, context, callback) => {
  context.callbackWaitsForEmptyEventLoop = false;
  const uuid = uuidv4();

  const uploadFile = async (image, uuid) =>
    new Promise(() => {
      // const bitmap = new Buffer(image, "base64"); // <====== deprecated
      const bitmap = Buffer.from(image, "base64"); // <======== problem here
      const params = {
        Bucket: "my_bucket",
        Key: `${uuid}.jpeg`,
        ACL: "public-read",
        Body: bitmap,
        ContentType: "image/jpeg"
      };
      s3.putObject(params, function(err, data) {
        if (err) {
          return callback(null, "ERROR");
        }
        return callback(null, "SUCCESS");
      });
    });

  parser(event).then(() => {
    uploadFile(event.body.file, uuid);
  });
};

getContentType () :

const getContentType = event => {
  const contentType = event.headers["content-type"];
  if (!contentType) {
    return event.headers["Content-Type"];
  }
  return contentType;
};

parser ()

const parser = event =>
  new Promise((resolve, reject) => {
    const busboy = new Busboy({
      headers: {
        "content-type": getContentType(event)
      }
    });

    const result = {};

    busboy.on("file", (fieldname, file, filename, encoding, mimetype) => {
      file.on("data", data => {
        result.file = data;
      });

      file.on("end", () => {
        result.filename = filename;
        result.contentType = mimetype;
      });
    });

    busboy.on("field", (fieldname, value) => {
      result[fieldname] = value;
    });

    busboy.on("error", error => reject(error));
    busboy.on("finish", () => {
      event.body = result;
      resolve(event);
    });

    busboy.write(event.body, event.isBase64Encoded ? "base64" : "binary");
    busboy.end();
  });

Ответы [ 2 ]

1 голос
/ 23 февраля 2020
new Buffer(number)            // Old
Buffer.alloc(number)          // New

new Buffer(string)            // Old
Buffer.from(string)           // New

new Buffer(string, encoding)  // Old
Buffer.from(string, encoding) // New

new Buffer(...arguments)      // Old
Buffer.from(...arguments)     // New
1 голос
/ 23 февраля 2020

Вы используете callbackWaitsForEmptyEventLoop, который в основном позволяет лямбда-функции думать, что работа еще не закончена. Кроме того, вы оборачиваете это в обещание, но не решаете это. Вы можете упростить эту логику c, используя следующую встроенную функцию обещания на aws-sdk

module.exports.main = async event => {
  const uuid = uuidv4();
  await parser(event); // not sure if this needs to be async or not. check
  const bitmap = Buffer.from(event.body.file, "base64"); // <======== problem here
  const params = {
    Bucket: "my_bucket",
    Key: `${uuid}.jpeg`,
    ACL: "public-read",
    Body: bitmap,
    ContentType: "image/jpeg"
  };
  const response = await s3.putObject(params).promise();

  return response;
};
...