mdrijwan
mdrijwan

Reputation: 59

Uploading image file to S3 using API gateway NodeJS

I'm trying to upload an image file to S3 using API Gateway. So it's a POST method where the body takes the image file using form-data. I wrote the lambda in TypeScript with the help of lambda-multipart-parser. It works fine locally but when i deploy it in AWS, the file size changes a bit and it seems the original file was not really uploaded properly.

my lambda code is

import * as parser from 'lambda-multipart-parser'
import { s3Upload } from '../helper/common'

export const test = async (event) => {
  console.log('starting------')
  console.log('EVENT', event)
  const result = await parser.parse(event)
  console.log(result.files)
  const file = result.files[0]
  console.log('FILE', file)

  const s3Params = {
    Bucket: process.env.AWS_BUCKET,
    Key: `${Date.now().toString()}-${file.filename}`,
    Body: file.content,
    ContentType: 'image/png',
    ACL: 'public-read',
  }
  console.log('S3 PARAMS', s3Params)
  const s3Content = await s3Upload(s3Params)
  console.log('S3 CONTENT', s3Content)
}

where i'm just calling the s3Upload from helper

import { S3 } from 'aws-sdk'

export const s3Upload = async function (params) {
  let s3: S3
  if (process.env.IS_OFFLINE) {
    s3 = new S3({
      accessKeyId: process.env.AWS_ACCESS_KEY,
      secretAccessKey: process.env.AWS_SECRET_KEY,
    })
  }
  return new Promise((resolve) => {
    s3.upload(params, (err, data) => {
      if (err) {
        console.error(err)
        resolve(err)
      } else {
        resolve(data)
      }
    })
  })
}

this looks like a problem of the node package itself but i'm not sure! what are the other working ways i can achieve this objective which is to upload an image file to S3 using API gateway written in typescript?

Upvotes: 1

Views: 3354

Answers (2)

sohaso
sohaso

Reputation: 135

Can you provide more information about your issue??

I took your code for testing locally. I found out that you need to instanciate the s3 again after the if is_offline.

import { S3 } from 'aws-sdk'

export const s3Upload = async function (params) {
  let s3: S3
  if (process.env.IS_OFFLINE) {
    s3 = new S3({
      accessKeyId: process.env.AWS_ACCESS_KEY,
      secretAccessKey: process.env.AWS_SECRET_KEY,
    })
  }

  // Here is the change

  s3 = new S3({
    region: 'us-east-1', // for example
  });
  return new Promise((resolve) => {
    s3.upload(params, (err, data) => {
      if (err) {
        console.error(err)
        resolve(err)
      } else {
        resolve(data)
      }
    })
  })
}

at least that worked for me. Also inside the lambda, also for local with serverless-offline, and also with an API Gateway, all with Typescript.

Hope this helps!

Regards!

Upvotes: 1

Albert
Albert

Reputation: 131

It is probably because the module is not included in the lambda, try to do npm init and install the package in the folder where the lambda or the other option is, and it is more advisable to create a layer and put the package there.

Here the documentation: https://docs.aws.amazon.com/cdk/api/v1/docs/aws-lambda-readme.html#layers

Upvotes: 0

Related Questions