Upload image file to S3 via api

Hi, I want to upload the jpg image to S3 bucket via api (image in post body). Is there anyone guide me how to do that? Thanks

There are few options to achieve this:

  1. Create a API endpoint as S3 proxy, so then you can give users ability to save file directly to S3
    Create an API as an Amazon S3 Proxy
  2. You send request to API gateway with lambda proxy and lambda returns the signedUrl to save file on S3, then using temporary credential you upload file to S3
  3. You send binary file to API endpoint and then just using lambda save to s3 (To do this you have to enable binary content types)
2 Likes

Hi Dawid, I tried no 2 but it is not working (is the same as an example that show in serverless framework github). For 1, it is a little bit to understand for me as I am new to AWS and serverless framework ecosystem. I want to and I am trying to do in third way but there is some problem. I can successfully upload the text file. For binary file(jpeg), it is not showing properly (just blank image) when I open the file in s3. Then what is “you have to enable binary content type”. I believe it meant to add (ContentType: “image/jpg”) along with bucket, key, body inside s3’s putObject function. If so, I already did. Do I need to add secret key and other credential info inside the code.
Many thanks,
Kind Regards,
John

You can checkout out this video: https://www.youtube.com/watch?v=BrYJlR0yRnw&t=83s

Have in mind that with the 3rd option your actual file size can be more less 4.5MB ( maximum size of lambda function request is around 6MB and you also have to count headers etc.). The body in lmabda will be base64 encoded, so when you call putObject on s3 bucket you actually have to do this:

import * as AWS from 'aws-sdk';

let s3 = new AWS.S3()
let buffer = Buffer.from(event.body, 'base64');  

let putObject = promisify(s3.putObject, s3) 

await putObject({
  Body: buffer,
  Bucket: 'YOUR_BUCKET_NAME',
  Key: 'FILE_NAME'    
  ContentDisposition: `attachment; filename=VISIBLE_FILE_NAME`
})  

The above code will not work, because it is in ES6 syntax

3 Likes

Hi Dawid, Thanks for you help. Finally, I decided to receive the code(image to base64) from client side via http post body and used that code as data for Body in “s3.putObject”. The problem is when I open the image on s3, it show error message on blank screen like

.
What would could this type of error? Do I need to specify security detail in the code. Currently I gave public read and write access to my bucket.
Many thanks,
Kind Regards,
John

Finally it works, after tried to put binary data in Body of s3’s putObject function. Thank you so much for your help and explain me how to do it @Dawid.
Cheers,
John

1 Like

I’m having the same issue and can’t seem to get it to work. The file doesn’t open in S3.

'use strict';

const AWS = require('aws-sdk');
const fs = require('fs');

module.exports.sendFile = (event, context, callback) => {
  
  console.log(event.body);
  
  var s3 = new AWS.S3();
  let buffer = Buffer.from(event.body, 'base64');

  console.log("Starting File saving!");

  var params = {Bucket: '...', Key: "TestFILE.png", Body: buffer, ContentEncoding: 'base64'};
    
    //console.log(params);
    
    s3.putObject(params, function(err, data){
      if (err) 
        { 
          console.log(err);
        } else {
          console.log('succesfully uploaded the image!');
        }
    });
  

  const response = {
    statusCode: 200,
    body: JSON.stringify({
      message: 'Go Serverless v1.0! Your function executed successfully!',
      input: event,
    }),
  };

  callback(null, response);
};

Am I doing something wrong as opposed to yours?

Thanks,
Kieran

You need to make change in some places.

let buffer = Buffer.from(event.body, ‘base64’); to let buffer = new Buffer(event.body, ‘base64’)
and
ContentEncoding is not ‘base64’. It is 'image/jpeg"

It should works now.
Cheers,
John

Hi John,

Oh brilliant! I’ll give that a shot. If I was to send videos and audio’s etc, would base64 be best for that. Like a universal content type?

Thanks,
Kieran

Hey Smiffy,

I am not pretty sure whether base64 is best for videos and audios. I am in the learning stage. May someone give you advice about that. By the way, have you tried my code? Is it working?

Cheers,
John

Amazon implements all of this for you in aws-amplify.

https://aws.github.io/aws-amplify/

https://aws.github.io/aws-amplify/media/storage_guide

1 Like

Hi John,

Serious apologies, did not mean to keep you waiting. I was kept well busy being on call in work. Haven’t even had time to look at my own stuff. Thanks a million for your help. Hopefully I will have time to try this soon.

Again sorry for the delay and thanks!

Kieran

Hi Jonsmirl,

Haven’t tried this! Thanks for showing it and I will give it a shot!

Kieran