Actionscript GZIP Alternative
I really wish Actionscript 3 had a native decompression utility for opening GZIP compressed files. I really do. After reading (and trying to implement the advice of) numerous postings, I gave up on GZIP.
In my investigation, I walked byte-by-byte through numerous binary dumps. Somewhere along the way I noticed a pattern. Forget about the head and foot bytes, the basic GZIP compressed data is simply not the same as the actionscript base deflate-algorithm compressed data.
People argue with me on that one. They say the compressed bytes are simply deflate-algorithm compressed and that these bytes can be decompressed by actionscript. I have but one comment. “Good luck with that, Cowboy. Knock yourself out.”
I have working code in production. Who you gonna believe?
I’ll start with the flex side first (flex3, as3). Use a URLLoader and set the dataFormat to BINARY or it will not work. Since the source data is not GZIP, I’ve made up a new file extension ‘xmlz’.
The code in listing 1 fetches the compressed XML, decompresses it and dumps it in a TextArea.
Listing 1. Simple Flex app to load compressed XML
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
backgroundGradientColors="[#ffffff, #c0c0c0]"
width="100%"
height="100%">
<mx:Script>
<![CDATA[
import flash.utils.ByteArray;
[Bindable]
private var bytes:String = "";
private var loader:URLLoader = new URLLoader();
private function urlLoaderSend():void
{
loader.addEventListener(Event.COMPLETE, setResult);
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.load(new URLRequest("http://example.com/data.xmlz"));
}
private function setResult(event:Event):void
{
var ba:ByteArray = loader.data as ByteArray;
ba.position = 0;
ba.uncompress();
bytes = ba.toString();
}
]]>
</mx:Script>
<mx:Button
label="get playlist"
click="urlLoaderSend()" />
<mx:TextArea
id="resultTA"
width="600"
height="600"
text="{bytes}" />
</mx:Application>
The server-side java is quite simple. I use the StAX XMLStreamWriter to generate XML. The writer’s constructor takes an OutputStream as an argument. Simply wrap the original OutputStream in a DeflaterOutputStream. The trick is to explicitly create the Deflater. If you don’t, the default will produce bytes incompatible with actionscript’s uncompress().
Listing 2. Java DeflaterOutputStream fragment (with StAX writer)
OutputStream out = new OutputStream();
⋮
Deflater d = new Deflater(Deflater.BEST_COMPRESSION, false);
OutputStream zipper = new DeflaterOutputStream(out, d);
XMLOutputFactory factory = XMLOutputFactory.newInstance();
XMLStreamWriter writer;
writer = factory.createXMLStreamWriter(zipper, "utf-8");
⋮
And that’s it! The compression is size-equivalent with GZIP (within a few bytes). I would rather actionscript supported GZIP. Until it does, I’ll continue using ‘xmlz’.
1 Comment
Thanks a lot! You saved me! I’ve spent my day to find a working server side Deflate algorithm without success.
In addition it works without XMLOutputFactory
zipper.write(“text”);
Kamela
10:14