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
2009.01.2810:14