DEV Community

Cover image for The Base64 Challenge!
Chad R. Stewart
Chad R. Stewart

Posted on • Updated on

The Base64 Challenge!

So when I started this project, there was a question on how I would accept images. In the project description, one of the choices was to accept them as base64 strings. This had intrigued me because I had heard about the technique previously from another job but had personally never used it. So I decided that this would be the approach that I would take and would learn a ton!

This turned out to be the biggest bottleneck in delivering the project initially.

The major unknown for me was decoding a base64 image and being able to work with it. I quickly grabbed a random image and took it to a website to encode it into base64. What I got back looked like gobbledygook to me or maybe even Matrix code. At best I recognized the ‘data:image/png…’ in the first part of the string while the rest might as well be in Japanese. And it was long… extremely, intimidatingly long…

My initial research led me in circles honestly. There was discussion of uploading base64 images but it wasn’t anything concrete to work with. It was pretty discouraging initially and actually pushed me to put the project on the back burner a few times. During this time, I would ask around for help with this. Mostly reaching out to Twitter and a few Backend friends that I had known who could have helped me. Unfortunately, I didn’t really hear back from them and just continued to go it alone.

Then I came across this example (shout-out to Pankaj Kumar):

Example Node Base64 Image Server
Example Node Base64 Image Server

In the above example, a node server takes a base64 image and decodes before writing it to disk. It validates that it’s a base64 string using a reject that checks for two things in the string, ‘data:’ and ‘base64,’. It then saves the text that follows which you can use in your decoding. I’m not proud to say it but I yoinked the whole thing initially. I didn’t know much about Buffers and how to use them and I definitely didn’t know about using them to decode base64 data. While I had tried to understand what the code initially meant, I had spent so much time not making any progress that I just wanted to continue with the project rather than spending any more time not moving forward. I did make a few modifications to the above example though.

It was important to me that I had utility functions that I could call whenever I wanted to decode a base64 image and so I spent some time structuring my code to make it easy to find things that I needed. That initially started with writing a file called prepare base64 img which would take the raw base64 string and pass it and whatever these utility functions would return around before returning a final result. One utility would extract the necessary pieces from the string and put them into Regex Arrays and return them. Another utility would actually do the decoding and writing to disk. I made sure to keep the Regex in its own file so that it was easy to find and easy to change if needed (honestly, I haven’t changed it since using it).

One of the biggest issues with this approach was writing the files to disk. This was very familiar to me from working on other Backend projects and so I quickly got used to working with this approach. The problem comes in with Node.js non-blocking I/O and the fact that you’re writing and reading from disk which is very slow in comparison to other approaches. When working with the filesystem, because of the asynchronous nature of JavaScript, it’s very easy to try and write to the filesystem and then try to use that file later on in your app only to find that there’s nothing there to use. This can be solved by using writefilesync from the fs package but, as I learned later on, this isn’t best practice because you want to take advantage of JavaScript being able to continue through your app while writing files to disk as opposed to holding the entire system up. It didn’t occur to me at the time though and honestly didn’t matter because I was making progress and that’s all that mattered. I had beaten base64 images and while I was bruised I hadn’t been stopped. I was just happy to be able to successfully implement base64 decoding.

Initially I returned the raw image in the server’s response, when I asked for some feedback on my work I was told that it would be better to pass it as a base64 string as well since that’s what the user would likely be expecting. Encoding an image was a significantly less challenge and it only really took a few Google searches before coming across a solution. It involved reading the image file from disk into base64 format and then adding the other necessary parts of the base64 string before passing it to the controller and then sending that response.

Here’s the commit when I finished the initial Base64 validation:

In the next article in this series, I tackle request validation.

Top comments (0)