I'm trying to upload the image (base64) from the postman, I can see when I hit the Serverless API, something has been added in S3 bucket but not image, I'm using nodejs Lambda function, I tried so many solutions but that didn't work out. Please suggest me where I'm wrong:

const AWS = require('aws-sdk');
const s3 = new AWS.S3();
const moment = require('moment');
const fileType = require('file-type');
const sha1 = require('sha1');
const multipart = require('parse-multipart');

exports.handler = function (event, context, callback) {

    let request = event.body;

    // get the request
    let base64String = request.base64String;

    // pass the base64 string into a buffer
    let buffer = new Buffer(base64String, 'base64');

    let fileMime = fileType(buffer);

    // check if the base64 encoded string is a file
    if (fileMime === null) {
        return context.fail('The string supplied is not a file type');
    }

    let file = getFile(fileMime, buffer);
    // let file = getFile(fileMime, parts);
    let params = file.params;

    s3.upload(params, function (err, data) {
    // putObject(params, function (err, data) {
        if (err) {
            console.log(err);
            callback(err);
        }

        // if the file object is uploaded successfully to 
        // s3 then you can get your full url
        console.log('File URL', file.full_path + JSON.stringify(data));
        callback(null, data);

    });
}

let getFile = function (fileMime, buffer) {

    // get the file extension
    let fileExt = fileMime.ext;
    let hash = sha1(new Buffer(new Date().toString()));
    let now = moment().format('YYYY-MM-DD');

    let filePath = hash + '/';
    let fileName = now + '.' + fileExt;
    let fileFullName = filePath + fileName;
    let fileFullPath = 'https://console.aws.amazon.com/s3/buckets/bucket-name/images/' + fileFullName;

    console.log('fileFullPath' + fileFullPath);
    let params = {
        Bucket: 'bucket-name',
        Key: fileFullPath,
        // 'this is simply the filename and the extension, e.g fileFullName + fileExt',
        Body: buffer
    };

    let uploadFile = {
        size: buffer.toString('ascii').length,
        type: fileMime.mime,
        name: fileName,
        full_path: fileFullPath
    }

    return {
        'params': params,
        'uploadFile': uploadFile
    }
}

Response in S3 bucket

when click on any of the response, the complete out is coming as an image

Postman base64 image string

Please let me know, where I'm missing some piece of codes. That will be appreciated.

1 Answers

7
Community On Best Solutions

When uploading objects to S3 that should be opened in a web browser, you need to set the correct content type. When S3 serves your object, the content type you set will be sent as a HTTP header.

Web browsers use MIME types to determine how to process URLs, not file extensions.

In your case, the content type is missing from the parameters your are passing to s3.upload. Moreover, the key is incorrect.

It should be:

const params = {
  Bucket: 'bucket-name',
  Key: fileFullName // must be a path within your bucket and not an url like you have in fileFullPath,
  Body: buffer,
  ContentType: fileMime.mime // Sets the content type header, without this your browser cannot infer the type (browsers use mime types, not file extensions)
};