How to Decode medium-editor Base64 Images and Upload Them to a S3 Bucket

Osusara Kammalawatta
3 min readAug 16, 2020

Let me tell you the problem I faced. In the project I’m currently working on, I had to create a text area with inline styling functionality. Just like the Medium.com text editor. So I used a JS package called medium-editor which has everything required in the project.

So, what is the problem? In medium-editor, user inputs are returning in HTML format. As an example, if we type “Hello, World!” in the text area, it will return it as <p>Hello, World!</p> Also, users can drag and drop or copy and paste images to add them. Just like in Medium.com. These images also return in HTML format by converting to base64. So, if a user adds an image, it’ll return a huge HTML with a base64 encoded image. We didn’t want to save the huge HTML in the database. So my plan was to,

  1. extract the images
  2. decode and upload them to an AWS S3 Bucket
  3. replace the base64 with image URI
  4. save the new HTML to database

I didn’t found a proper answer for this on the internet. So, I am writing this from what I found. Hope it’ll help you.

Extract images

Think, a user input some text and an image in our text area. The medium-editor will convert it to HTML format as something like this,

<p class="">Hello, World!</p>
<p class="">I'm Osusara Kammalawatta</p>
<img class="" src="data:image/png;base64,iVBORwGgoAAAAUhEU...." />

First, we have to get the src values of all the images. I have used a regex with match() function as below,

const encodedImages: any = HTMLfromME.match(
/data:image\/([a-zA-Z]*);base64,([^\"]*)/g,
);

HTMLfromME is the value comes from medium-editor and it is a large string in HTML format. The above function will return an array of base64 images.

Decode and upload them to an AWS S3 Bucket

Now we got all the images but in base64 format. So we have to decode and upload them to S3 Bucket.

For that, first I created a S3 Bucket. I’m not going to explain about AWS S3 here, because it is a whole different topic. After creating a S3, make sure to give necessary access permissions. I made my bucket policy public by adding this,

{
"Version": "2012-10-17",
"Id": "Policy1555582784303",
"Statement": [
{
"Sid": "Stmt1555582783256",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::S3_BUCKET_NAME/*"
}
]
}

After that I map() each image from encodedImages array, decode them and uploaded them one by one as below,

encodedImage.map(image => {
const buf = Buffer.from(
image.replace(/^data:image\/\w+;base64,/, ''),
'base64',
);
const data = {
Key: "PATH_TO_SAVE_IMAGES_IN_S3/NAME_FOR_IMAGE.jpg",
Body: buf,
Bucket: "S3_BUCKET_NAME",
ContentEncoding: 'base64',
ContentType: 'image/jpeg',
};
s3.putObject(data, (err, data) => {
if (err) throw err;
});
// More codes
}

In data object, make sure to add a dynamic Key value, which changes for each image. Key is the path and filename we are going to save in S3. And that value is the one we are going to replace with the src in <img> tags.

Replace the base64 with image URI

This part also should do inside the map() function. We are going to replace each image src as they upload to S3 Bucket.

evidence.content = HTMLfromME.replace(
image,
"S3_BUCKET_URL/PATH_TO_SAVE_IMAGES_IN_S3/NAME_FOR_IMAGE.jpg",
);

I think you can understand what is happening. We are replacing the whole src value which is currently in image variable with, uploaded image URI. Make sure you add the S3 Bucket URL at the beginning.

S3_BUCKET_URL/PATH_TO_SAVE_IMAGES_IN_S3/NAME_FOR_IMAGE.jpg This part should be the URI to access the image we uploaded in S3.

save the new HTML to database

Now we have the HTML with images URIs. So, we can save it to the database. In this project, we have used AWS RDS as the database. I’m not going to explain about it because RDS also a whole different topic and this article is not about it. It’s not that difficult. Hope you learned something from this article. Feel free to response.

Happy Coding Folks 👽

--

--