Is it possible to pass File Object to AWS Lambda through API Gataway in javascript?

Viewed 824

Is it possible to pass JavaScript File Object from browser to AWS Lambda through API Gateway (finally to S3). I am using TypeScript and React.

Environment

Frontend

  • TypeScript
  • React
  • AWS Amplify (to use API module)

Backend(AWS Lambda)

  • Node.js

What's expected

to pass File Object, which got from browser by <input type='file'>, to backend aws lambda through API Gateway.

What's happening

console.log(event) at backend, the log output was empty.

What I want to know

the way how to pass File Object(Blob) to lambda correctly. (Just a link to document, it'll also really help me.)

Code (Frontend)

import { API } from 'aws-amplify'
...
const file = { body: this.state.file }
console.log(file) // output was collect File Object at this time
API.post(<API_NAME>, <PATH>, file)
  .then(response => {
    console.log(response)
  }).catch(error => {
    console.log(error)
  })

Code (Backend)

exports.lambdaHandler = function (event, context, callback) {
  console.info(`event.body: ${event.body}`) // got `event.body: {}` at Cloud Watch Logs
  ...
}

Is it possible what I'm trying to do by setting Content-Type or something? (I couldn't find any documentation. I've been started programming just only for one year).

2 Answers

I disagree with sidali's answer for many reasons (security, cost, ...). You would not want a publicly accessible S3 bucket.

It is recommended to request a presigned URL for S3 over your API Gateway + Lambda. With that URL only the specific user would be able to upload a file for a defined period of time (e.g., 1 minute or 5 hours).

const getSignedUrlForUpload = async () => {
  const params = {
    Bucket: BUCKET_NAME,
    Key: 'AWS_Cloud_Best_Practices.pdf',
    Expires: 60,
    ContentType: 'application/pdf',
  }


  const url = await new Promise((resolve, reject) => {
    s3.getSignedUrl('putObject', params, (err, url) => {
      if (err) reject(err)

      resolve(url)
    })
  })

  return url
}

uploadFileToS3()
  .then((res) => {
    console.log(res)
  }).catch((e) => {
    console.log(e)
  })

Source: https://arpadt.com/articles/presigned-urls-in-node#34-upload-link

You have to upload you file into s3 directly to a specific Bucket, and create lambda trigger event on s3 upload on this particular Bucket,

This way lambda will trigger each time you send a file, you can there read your file and do your process.

Please read https://docs.aws.amazon.com/lambda/latest/dg/with-s3.html

Related