× {{alert.msg}} Never ask again
Get notified about new tutorials RECEIVE NEW TUTORIALS

Strategies for serving Base64 encoded images in HTML

Andy Maleh
May 11, 2015
<p>One fellow hit me up with a question today regarding how to display images obtained from Gmail's API using Ruby on Rails.</p> <p>To provide some background, the Gmail API has a method that can obtain an email message's multi-part structure in JSON based on the message ID. For each inline image, there is an attachment ID that can be used to make a second Gmail API call and obtain the image Base64-encoded body, which can be used alongside the image mime type to display the image to the user.</p> <p>The question was about the best strategy to do so.</p> <p>Here are 3 strategies, listed progressively in complexity:</p> <p>1. Embed images directly in the HTML using base64 data URLs as the src attribute value of img tags. </p> <p>Here is an example of how this works:</p> <pre><span style="color:rgb(0, 153, 0)">&lt;<strong>img</strong> <span style="color:rgb(0, 0, 102)">src</span><span style="color:rgb(102, 204, 102)">=</span><span style="color:rgb(255, 0, 0)">"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA</span> </span><span style="color:#FF0000">AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO 9TXL0Y4OHwAAAABJRU5ErkJggg==</span><span style="color:rgb(0, 153, 0)">" </span>alt<span style="color:rgb(0, 153, 0)">="</span><span style="color:#FF0000">Red dot</span><span style="color:rgb(0, 153, 0)">" <span style="color:rgb(102, 204, 102)">/</span>&gt;</span></pre> <p>And here is more info to learn more about it: <a href="http://en.wikipedia.org/wiki/Data_URI_scheme">http://en.wikipedia.org/wiki/Data_URI_scheme</a></p> <p>2. Add an extra URL action on the server to be responsible for obtaining an image from Gmail based on attachment ID, and use that URL as the src attratibue value of img tags.</p> <pre><span style="color:rgb(0, 153, 0)">&lt;<strong>img</strong> <span style="color:rgb(0, 0, 102)">src</span><span style="color:rgb(102, 204, 102)">=</span><span style="color:rgb(255, 0, 0)">"/messages/[messageID]/images/[attachmentID]</span>" <span style="color:rgb(0, 0, 102)">alt</span><span style="color:rgb(102, 204, 102)">=</span><span style="color:rgb(255, 0, 0)">"Red dot"</span> <span style="color:rgb(102, 204, 102)">/</span>&gt;</span></pre> <p>Ensure that server-side code returns the right image mime type upon hitting that URL (e.g. image/png) and decoding the base64 before sending it as the response body.</p> <p>3. Download email images to a local server upon fetching the email message from Gmail, and then replace src attribute value with actual local server image URL for every img tag in the email HTML document</p> <p>Example:</p> <pre><span style="color:rgb(0, 153, 0)">&lt;<strong>img</strong> <span style="color:rgb(0, 0, 102)">src</span><span style="color:rgb(102, 204, 102)">=</span><span style="color:rgb(255, 0, 0)">"/images/email-image-321.png</span>" <span style="color:rgb(0, 0, 102)">alt</span><span style="color:rgb(102, 204, 102)">=</span><span style="color:rgb(255, 0, 0)">"Red dot"</span> <span style="color:rgb(102, 204, 102)">/</span>&gt;</span></pre> <p> </p> <p>Now, let's discuss pros and cons.</p> <p>#1 is simplest, but yields larger HTML document downloads, which can affect performance as users have to wait for all images to download from the Gmail API servers before they see the email. This can be mitigated for subsequent visits (but not initial visits) by caching HTML responses on the server-side.</p> <p>#2 is more complex, but makes it much faster to see and read email messages while their images are downloading with extra web browser background calls. It also allows parallel processing of multiple image downloads with multiple server calls, taking advantage of any scalability on the backend, such as multi-cores or multiple server machines. Finally, it can still take advantage of caching just like #1, making subsequent email message visits much faster.</p> <p>#3 is most complex, but serves as a caching mechanism for images that obviates the need for creating a second image URL action handler on the server-side as cached images get saved as part of the main email message action handling, thus later serving images directly from image file URLs like /images/image-name.png</p> <p>One more thing to note about #1's approach of embedding images directly is that it is supported only from IE8 and up by Microsoft's web browser (not an issue), and while IE9 and up put on cap on image size, IE8 limits it to about 32k.</p> <p>Good luck building your next Base64-encoded image-serving website</p>

Get New Tutorials Delivered to Your Inbox

New tutorials will be sent to your Inbox once a week.

comments powered by Disqus