Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Image file is not viewing uploaded by s3

I am uploading image files using s3. But whenever I try to download using the URL as well as from the s3 console will download the image file. But, it will not visible to the image viewer. It just shows an incompatible file type.

myS3Function.uploadFile(request.body.fileName, request.files.myFileData, "image_folder").then(filename => {
 //success
})

.

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

const s3 = new AWS.S3({
 region: process.env.REGION
});

exports.uploadFile  = (filename, data, folderName) => {
return new Promise((resolve, reject) => {
    const params = {
        Bucket: process.env.AWS_S3_BUCKET, 
        Key: folderName+'/'+filename,
        Body: data.data,
        ACL:'public-read',
        ContentType: "image/jpeg"
    };
    s3.upload(params, function(s3Err, data) {
        if (s3Err) reject(s3Err)
        console.log(`File uploaded successfully at ${data.Location}`)
        resolve(`${data.Location}`)

    });
});
}

I uploaded files using postman now as form data. I can see text files uploaded using this code correctly. Then why do images have the issue? Also, images and pdf actual file size is increased a little bit.

enter image description here

enter image description here

like image 998
KIRAN K J Avatar asked Oct 18 '25 10:10

KIRAN K J


2 Answers

As indicated in the different comments of your question, there are several things that can motivate your problem.

Please, be sure that you are providing the necessary configuration about the different content types that should be considered binary. The AWS documentation provides great detail about it; this related SO question can be valuable as well.

Due to the fact you are using the serverless framework, as indicated in the links 1 2 you cited, please provide the necessary configuration there as well:

provider:
  apiGateway:
    binaryMediaTypes:
      - 'multipart/form-data'

In any way, it seems that even with this configuration, you are still facing the problem. You told you were able to successfully upload text files, but your images get corrupted, increasing their size: as indicated in the comments, it seems a clear indication that in some place the information is being converted to a different encoding, from binary to text, something like that. In fact, according to your dependencies, this seems to be the actual problem ,as reported in this issue of the serverless-http library and especially, in this others 1 and 2 of the serverless-offline library.

I think the issue is only local and that it will probably work without further problems in AWS.

In any way, as you can see in first of the above mentioned issues, the one related to serverless-http, the library has the following code:

return Buffer.from(event.body, event.isBase64Encoded ? 'base64' : 'utf8'); 

So, as a workaround, submitting your information as base 64 encoded can solve the issue: it is not a straightforward task if you are using form submission in your HTML - see for instance this great example for some ideas - although it can do the trick if you interact directly with your API from code. The only necessary change is in your params variable:

const params = {
  Bucket: process.env.AWS_S3_BUCKET, 
  Key: folderName+'/'+filename,
  Body: Buffer.from(data.data, 'base64'),
  ContentEncoding: 'base64',
  ContentType: 'image/jpeg',
  ACL:'public-read',
};

Please, note the use of Buffer.from(..., 'base64') and the inclusion of ContentEncoding: 'base64'.

In any way, if the code works in AWS I think the way to go would be waiting for the serverless-offline issues resolution.

like image 56
jccampanero Avatar answered Oct 19 '25 23:10

jccampanero


I'm not sure what the problem is, but it seems like serverless offline is having trouble processing the data coming in as multipart/form-data. The easiest solution would be to encode the file as base64 and send the payload as application/json.

To encode the file as base64, use this website: https://base64.guru/converter/encode/file. It is trivial to do this locally and programatically, but the website is cross-platform and should be good enough for testing.

Request

enter image description here

Payload:

{

    "fileName": "sampleFile.jpg",
    "myFileData": "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",
    "fileType": "image/jpeg",
    "productId": 12,
    "isDefault": false,
    "position": 2
}

product-image.js

const s3Functions = require('../services/s3Functions')
const { KEY_S3_PRODUCT_IMAGES_FOLDER } = require('../util/constants');
const { KEY_STATUS, KEY_DATA } = require('../util/constants');

exports.uploadProductImage = (body) => {
    return new Promise((resolve, reject) => {
        s3Functions.uploadFile(
            body.fileName,
            body.myFileData,
            body.fileType,
            KEY_S3_PRODUCT_IMAGES_FOLDER
        ).then(filename => {
            resolve({ [KEY_STATUS]: 1, [KEY_STATUS]: "Uploaded successfully", [KEY_DATA]: filename });
        }).catch(error => {
            reject({ [KEY_STATUS]: 0, [KEY_STATUS]: "Upload Failed", [KEY_DATA]: error });
        });
    })
}

s3Functions.js

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

const s3 = new AWS.S3({
    params: { Bucket: 'rename-me', ACL:'public-read' },
});

exports.uploadFile = (
    filename,
    data,
    contentType,
    folderName
) => {
    console.log('Uploading')
    return new Promise((resolve, reject) => {
        const params = {
            Key: folderName+'/'+filename,
            Body: Buffer.from(data, 'base64'),
            ContentEncoding: 'base64',
            ContentType: contentType,
        };
        s3.upload(params, function(s3Err, data) {
            if (s3Err) {
                console.error(s3Err);
                reject(s3Err)
            }
            console.log(`File uploaded successfully at ${data.Location}`)
            resolve(`${data.Location}`)
        });
    });
}

Here's the codebase you provided on the other thread, with the included changes. I haven't cleaned it up, but just in case you run into any issues.

like image 45
dhruvit-r Avatar answered Oct 20 '25 00:10

dhruvit-r



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!