Search code examples
node.jsamazon-web-servicesamazon-s3aws-lambdaaws-api-gateway

Image uploaded to S3 becomes corrupted


I’m having issues uploading a file from postman to aws lambda + s3. If I understand correctly the image has to be a base64 string and send via JSON to work with lambda and API Gateway so I converted an image to a base64 and I’m using the base64 string in postman

enter image description here

The file uploads to S3, but when I download the s3 object and open it I get

enter image description here

So I don’t think I’m uploading it correctly. I’ve used a base64 to image converter and the image appears so the base64 string is correct before sending it via postman so something in my setup is off. What am I doing wrong? I appreciate the help!

upload.js

const AWS = require('aws-sdk');
const s3 = new AWS.S3();
exports.handler = async (event, context, callback) => {
    let data = JSON.parse(event.body);
    let file = data.base64String;


    const s3Bucket = "upload-test3000";
    const objectName = "helloworld.jpg";
    const objectData = data.base64String;
    const objectType = "image/jpg";
    try {
        const params = {
            Bucket: s3Bucket,
            Key: objectName,
            Body: objectData,
            ContentType: objectType
        };
        const result = await s3.putObject(params).promise();
        return sendRes(200, `File uploaded successfully at https:/` + s3Bucket + `.s3.amazonaws.com/` + objectName);

    } catch (error) {
        return sendRes(404, error);
    }
};
const sendRes = (status, body) => {
    var response = {
        statusCode: status,
        headers: {
            "Content-Type": "application/json",
            "Access-Control-Allow-Headers": "Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token",
            "Access-Control-Allow-Methods": "OPTIONS,POST,PUT",
            "Access-Control-Allow-Credentials": true,
            "Access-Control-Allow-Origin": "*",
            "X-Requested-With": "*"
        },
        body: body
    };
    return response;
};

.png


Solution

  • I got it working by adding the base64 string in JSON format like so

    enter image description here

    and then sent

    let decodedImage = Buffer.from(encodedImage, 'base64'); as the Body param.

    updated upload.js

    const AWS = require('aws-sdk');
    var s3 = new AWS.S3();
    
    
    exports.handler = async (event) => {
    
        let encodedImage = JSON.parse(event.body).base64Data;
        let decodedImage = Buffer.from(encodedImage, 'base64');
        var filePath = "user-data/" + event.queryStringParameters.username + ".jpg"
        var params = {
            "Body": decodedImage,
            "Bucket": process.env.UploadBucket,
            "Key": filePath
        };
    
        try {
            let uploadOutput = await s3.upload(params).promise();
            let response = {
                "statusCode": 200,
                "body": JSON.stringify(uploadOutput),
                "isBase64Encoded": false
            };
            return response;
        }
        catch (err) {
            let response = {
                "statusCode": 500,
                "body": JSON.stringify(eerr),
                "isBase64Encoded": false
            };
            return response;
        }
    
    };
    
    

    I found this article to be super helpful