HTML images using long GET strings

The Problem

You’ve got a piece of code that creates an image in your web page by passing a bunch of parameters in a GET string to some server-side process:

$('tile').src = 'http://img.com/generate.php?a=1&b=2&c=3';

But what do you do when the URL goes beyond the limit? Practically, for cross-browser solutions, the limit is around 2000 characters (thanks to IE), and I recently had to find a workaround when generating images via a WMS.

The Solution

When we’re dealing with HTML forms, if a GET isn’t big enough we have to use a POST. The difficulty in the scenario described above is that there’s no way to provide the POST variables when making the assignment to the image’s src attribute.

I thought about how to use an Ajax POST but even if image data could be streamed back to the browser in this way, there’s no mechanism for getting it into an HTML image.

And then I discovered the data URI scheme which allows us to assign a base64 representation of an image to an HTML image like so (where the ellipsis indicates the position of the base64 data string):

$('tile').src = 'data:image/gif;base64,...';

If I could issue a POST to the server to generate my image, I could convert that image into a base64 string to pass back to the browser, which I could then utilise in the data URI scheme syntax.

I discovered this method in this brilliant post where the same trick is used to for CSS and to reduce HTTP requests. And by reading that post I learned that we have to do it another way in IE. In IE we have to use MHTML and it involves a little more work on the server but we can still end up with this (where somestring indicates the position in mhtml.txt of the base64 data string):

$('tile').src = 'mhtml:http://img.com/mhtml.txt!somestring';

A proxy script on the server is required to pass the POST variables through to the image-generation program, and convert the resultant image into a base64 data string. Since the WMS I use is located on an external server I was already using Troy Wolf’s PHP proxy script (note that it requires class.php). Converting to base64 is a cinch in PHP:

$base64_encoded_image = base64_encode($response);

I simply added the code I needed to the end of Troy’s proxy script.

So, the flow of events is:

  • Client issues an Ajax POST request to the proxy script.
  • Proxy forwards the request to the image-generation program and converts the resultant image into a base64 data string.
    • For IE, the proxy saves the string to a file and returns the filename to the client.
    • For all other browsers, the proxy returns the string to the client.
  • Client’s Ajax “on success” callback assigns the relevant string to the HTML image’s src attribute.

Anyway, here’s a demo page.
And here’s a zip containing all the necessary files.

A Few Considerations

The IE workaround involves creating a file on the server that contains the base64 representation of the generated image. The format of the file must be as follows in terms of line breaks, and in terms of the double quotes around the boundary parameter:

Content-Type: multipart/related; boundary="_ANY_SEPARATOR"

--_ANY_SEPARATOR
Content-Location:somestring
Content-Transfer-Encoding:base64

R0lGODlh...snip...AACgAACoAAC

The folder in which the MHTML files are generated obviously requires the appropriate privileges. If this method were used in a production environment an automated procedure would be required to delete periodically old MHTML files. IE8 is a great improvement over previous versions and actually supports the data URI scheme, so one day in the distant future all the MHTML workaround shenanigans will be unnecessary. But until then we’re stuck with having to write a file to the server every time – and if we’re doing that it might be preferable simply to write the image to the server and return its URL to the browser. At least it would mean no JavaScript browser-sniffing, and that’s no bad thing.

Leave a Reply