Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to retrieve multiple image from Amazon S3 using imgURL at once?

I want to retrieve list of images in one go from Amazon S3 based on image URL.

Currently I am able to fetch single image using the following code:-

     AWS.config.update({
                    accessKeyId: accessKeyId,
                    secretAccessKey: secretAccessKey
                });

                AWS.config.region = region;

                var bucketInstance = new AWS.S3();
                var params = {
                    Bucket: bucketName,
                    Key: awsImgUrl
                }
                bucketInstance.getObject(params, function (err, file) {
                    if (file) {
                        var dataSrc = "data:" + file.ContentType + ";base64," + EncodeData(file.Body);
                        callbackSuccess(dataSrc);
                    } else {
                        callbackSuccess("Error");
                    }
                });

EncodeData = function (data) {
        var str = data.reduce(function (a, b) { return a + String.fromCharCode(b) }, '');
        return btoa(str).replace(/.{76}(?=.)/g, '$&\n');
    }

In my scenario I have multiple S3 image url like awsImgUrl1, awsImgUrl2..awsImgUrln.

How to fetch it in one go instead of one by one?

like image 362
simple user Avatar asked Oct 06 '18 04:10

simple user


2 Answers

You cannot get more than one image per api call with S3. You can however make multiple calls in parallel. Using promises this is straightforward.

var bucketInstance = new AWS.S3();
var imageKeys = [ awsImgUrl1, awsImgUrl2, awsImgUrl3];

var promisesOfS3Objects = imageKeys.map(function(key) {
  return bucketInstance.getObject({
    Bucket: bucketName,
    Key: key
  }).promise()
    .then(function (file) {
      return "data:" + file.ContentType + ";base64," + EncodeData(file.Body);
    })
  })
Promise.all(promisesOfS3Objects)
.then(callbackSuccess) // callbackSuccess is called with an array of string
.catch(function() { callbackSuccess("Error") })
like image 200
cementblocks Avatar answered Sep 30 '22 18:09

cementblocks


You can change the way you upload the image data. Instead of uploading a single image, upload one document containing multiple image datas.

const addImageBlock = () => {
  var photoBlock = [
    {
      imageId: 'id',
      type: 'png',
      body: 'data:image/png;base64,iVBORw0K...'
    },
    {
      imageId: 'id2',
      type: 'png',
      body: 'data:image/png;base64,iVBORw0K...'
    },
    {
      imageId: 'id3',
      type: 'png',
      body: 'data:image/png;base64,iVBORw0K...'
    },
    {
      imageId: 'id4',
      type: 'png',
      body: 'data:image/png;base64,iVBORw0K...'
    }
    //...ect
    ];
  s3.upload({
    Key: photoBlockId + '.json',
    Body: photoBlock,
    ACL: 'public-read'
  }, function(err, data) {
    if (err) {
      return alert('There was an error', err.message);
    }
  });
}

Then when you receive this data with one s3 call, you can loop through and render the images on the frontend,

getObject(params, function (err, file) {
   imageArr = [];
    if (file) {
       JSON.parse(file.toString()).map((image) => {
      var image = new Image();
      image.src = image.body;
      imageArr.push(image)
    })
       callbackSuccess(imageArr);
                    } 
    else {
      callbackSuccess("Error");
         }
});
like image 30
Ryan Breece Avatar answered Sep 30 '22 17:09

Ryan Breece