Recently I was tasked with writing a Java Servlet to consume images from a 3rd party REST Service and serve them up via JSP. Shortly after getting started, I realized that image was being transmitted as binary so I needed to find a way to display them on the page without having to store them on the web server. My first solution was to convert the binary to a Base64 encoded string and use a Data URI scheme embeded in the HTML img tag. This seemed to work beautifully, that is until I had do do cross browser comparability testing. Because the images that the 3rd party service were serving up were greater than 32Kb, I discovered that IE8 fails miserably here.
The Problem
It didn’t take long for me to come across the Microsoft Documentation that states:
"Data URIs cannot be larger than 32,768 characters"
The documentation later goes on to state that the 32Kb DATA URI limit is removed in IE9 (which is why my preliminary testing did not catch it.)
The Resolution
Luckily, I over complicated original issue. The requirements were to create a servlet that called a REST Service for an image (based on some ID passed into the page) and display that image on the front end JSP. Using a Data URI scheme was not in the requirements but was an idea passed to me by a friend of mine. It turns out, that placing the binary response directly into the HTML img tag works just as well (and also saves on overhead of using Base 64 encoding).
The Code
The Servlet Code (Using Apache Components Library: HttpClient)
... //Code above sets the following variables: //SlingHttpServletResponse response --> response object passed into the servlet //GetMethod get --> object sending the GET request //HttpClient client --> Client object to handle the client actions int status = client.executeMethod(get) if (status == 200) { byte[] imageBytes = get.getResponseBody(); response.setContentType("image/png"); //in this case all images are pngs response.setContentLength(imageBytes.length); response.getOutputStream().write(imageBytes); } else { //something went wrong time to fail out out.println("Image service failed..."); } ...
The JSP code to display image response directly on front end
... <img src="/path/to/image/servlet?assetID=<%=imageId%>" /> ...
The direct binary response from the servlet can be place in the image source directly. This will get around the IE8 32Kb size restriction.
Oh nooozzz. I didn’t know you were moving forward with the base 64 solution. I generally consider re-encoding anything bad practice simply due to the fact that information can be lost (not in this example, but in many others).
Usually I’d recommend a common browser accepted capability (being bias usually to cope with Microsoft’s previous lack of W3C conformance). I still consider that a bit of a hack, haha, but I’m glad you used a different approach!
I still maintain the complaint that this implementation is not cacheable, thus creating just as much overhead/bandwidth usage as using base64.
Always enjoy reading. Thanks John!
I forgot to mention in the post, but CQ5 does caching at the dispatcher level. So the image does get cached at the dispatcher level once at least one person has viewed the page with the image. For author and publish instances it will regenerate all the time, but site visitor’s only go to the site through the dispatcher so caching is in tact.
However, prior to this exercise, I had no idea that you could just return the bits directly to the src attribute in the img tag. … You learn something new every day!