Retrieving and Converting Images from Amazon S3 to Base64 Efficiently

Hello everyone!

I need to grab several image-files from Amazon S3 and convert it to Base64.
What's the best way to do this for a list of images?
Or is there a way to get the files directly in Base64 from S3?

Any tips or examples would be super helpful! Thank you!

Hi @frank01zeroy! Welcome to Retool.

I would set up a workflow. There a plenty of ways you could do this. On a basic level:
Set up a REST API Resource. Use the GET method to fetch the image from S3.
Example URL: https://your-bucket.s3.amazonaws.com/path-to-image.jpg.

Depending on where your list is and your naming conventions you could loop through your list of images.

Use JavaScript to Convert the Image to Base64. Add a JavaScript transformer to process the fetched data.

Example

const fetchImageAsBase64 = async (url) => {
  try {
    const response = await fetch(url);
    const blob = await response.blob();
    
    return new Promise((resolve) => {
      const reader = new FileReader();
      reader.onloadend = () => resolve(reader.result.split(',')[1]); // Remove the "data:image/*;base64," prefix
      reader.readAsDataURL(blob);
    });
  } catch (error) {
    return `Error fetching image: ${error}`;
  }
};

// Example: Convert multiple images
const imageUrls = [
  "https://your-bucket.s3.amazonaws.com/image1.jpg",
  "https://your-bucket.s3.amazonaws.com/image2.jpg",
];

Promise.all(imageUrls.map(fetchImageAsBase64))
  .then(base64Images => console.log(base64Images))
  .catch(error => console.error(error));

This should get yo started. Feel free to share screenshots and more details if you need more help. :grinning:

1 Like

Hey! I’ve run into this issue before. Looks like Amazon S3 and Retool don’t support fetching multiple images in Base64 all at once. In my app, I used a Promise mechanism with additionalScope to get the Base64 for each file separately.
Let me know if you have any questions.

async function fetchImages() {
  const imageKeys = listObjectsQuery.data.Contents.slice(0, 10).map(obj => obj.Key);

  const imagePromises = imageKeys.map(async (key) => {
    const imageData = await s3GetObjectQuery.trigger({ additionalScope: { key } });
    return imageData.Body;
  });

  return await Promise.all(imagePromises);
}

return fetchImages();
2 Likes