Ad

Image File Upload To Aws Lambda Using AWS Api Gateway

I am trying to create a lambda function which accepts an image as multipart/form-data, do some processing on the image and upload it to s3 and also returns reponse to the client. But i am stuck at the very first part of uploading the image to aws lambda using API gateway. I tried to do this in NodeJS as shown below:

exports.handler = async (event, context, callback) => {
  var buf = Buffer.from(event.body.replace(/^data:image\/\w+;base64,/, ""),"base64");

  var data = {
    Bucket: "bucket-name", 
    Key: "abc.jpg", 
    Body: buf,
    ContentType: 'image/jpg',
    ACL: 'public-read'
  };
  data = await s3.upload(data).promise();
  return {
         statusCode: 200,
         body: JSON.stringify(buf),
     };

I am getting the following response in Postman by making POST request to the api:

{
    "ETag": "\"b0e5b18d38904f109e0aef0b29e132be\"",
    "Location": "https://bucket-name.s3.us-east-2.amazonaws.com/abc.jpg",
    "key": "abc.jpg",
    "Key": "abc.jpg",
    "Bucket": "bucket-name"
}

But when i try to view the uploaded image in my browser using public url in the returned in the above response, i am getting empty image.

Can somebody point me the mistake here or suggest some better approach. Thank you.

Ad

Answer

As suggested by Ashan, you can go with best practice of uploading images via browser.

If the image size is not that large, here is working example of uploading image to S3 via ApiGateway/Lambda Proxy Integration.

Lambda Function Code -

exports.handler = (event, context, callback) => {
  let encodedImage = JSON.parse(event.body).user_avatar;
  let decodedImage = Buffer.from(encodedImage, 'base64');
  var filePath = "avatars/" + event.queryStringParameters.username + ".png"

  var params = {
    "Body": decodedImage,
    "Bucket": "bucketName",
    "Key": filePath,
    "ContentType " : "mime/png"
  };
  s3.upload(params, function (err, data) {
    if (err) {
      callback(err, null);
    } else {
      let response = {
        "statusCode": 200,
        "body": JSON.stringify(data),
        "isBase64Encoded": false
      };
      callback(null, response);
    }
  });
};

Serverless.yml

service: aws-api-lambda-s3-image-upload

frameworkVersion: ">=1.1.0 <2.0.0"

provider:
  name: aws
  runtime: nodejs8.10
  iamRoleStatements:
    -  Effect: "Allow"
       Action:
         - "s3:ListBucket"
       Resource: "arn:aws:s3:::bucketName"
    -  Effect: "Allow"
       Action:
         - "s3:PutObject"
       Resource: "arn:aws:s3:::bucketName/*"

functions:
  index:
    handler: handler.handler
    events:
      - http: POST handler

Json Payload Should be -

{
  "user_avatar" : "<<base64 encoded image>>"
}
Ad
source: stackoverflow.com
Ad