I’ve recently had to write an unzipper for updating local files of an AIR-app!
Searching the internet I’ve found some very powerful unzipper libraries.
First I’ve tried it with the AS3 FZip library.
Although it worked pretty well in the beginning and no errors occured, I got the problem that this library wasn’t able to unzip correctly meaning that I got a lot of broken files!
So I tried it with the well known nochump-library which turned out to be a very good solution to my problem!
First off, get the nochump zip-libraries, as you will need it for this Unpacker Class: nochump zip library
The core functionality of this class is, that you are easily able to load a zip file from the internet and unpack it to your local filesystem.
usage
To use this class simply create a new instance and call the unpack function!
import com.firsara.utils.Unpacker;
unpacker = new Unpacker("output_directory");
unpacker.unpack("http://www.example.com/path_to_your_zip_file.zip");
unpacker.addEventListener(ProgressEvent.PROGRESS, showProgress);
unpacker.addEventListener(Unpacker.UNPACK_FILE, showUnpack);
unpacker.addEventListener(Event.COMPLETE, unpackComplete);
As you can see above you can also watch for three events.
The First one shows you the current download progress of your zip file.
You can access the progress through
unpacker.percentage
The second events gets dispatched when a file is being unzipped.
Even though this process does not take long it can still be interesting to display the current File that gets unzipped. To get the current File you can output
unpacker.currentFile
in your event handler!
That’s quite all you need to know…
The complete class looks like this:
Unpacker class
package com.firsara.utils
{
import nochump.util.zip.*;
import flash.utils.setTimeout;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.events.EventDispatcher;
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
import flash.net.URLRequest;
import flash.net.URLStream;
import flash.net.URLLoader;
public class Unpacker extends EventDispatcher
{
public static const UNPACK_FILE:String = "unpack";
private var _directory:String;
private var _currentFile:String;
private var _percentage:Number;
private var _stream:URLStream;
private var _zipFile:ZipFile;
public function get percentage():Number { return _percentage; }
public function get directory():String { return _directory; }
public function get currentFile():String { return _currentFile; }
public function unpack(url:String):void
{
if (url.indexOf('http://') < 0) url = 'http://' + url;
_stream = new URLStream();
_stream.load(new URLRequest(url));
_stream.addEventListener(ProgressEvent.PROGRESS, showProgress);
_stream.addEventListener(Event.COMPLETE, extract);
}
public function Unpacker(dir:String):void
{
_directory = dir;
_percentage = 0;
if ((_directory != "") &&
(_directory.charAt(_directory.length - 1) != "/"))
{
_directory += "/";
}
_directory.replace(/\\/gi, "/");
}
private function showProgress(event:ProgressEvent):void
{
_percentage = Number(event.bytesLoaded / event.bytesTotal);
dispatchEvent(event);
}
private function dispatchComplete():void
{
dispatchEvent(new Event(Event.COMPLETE));
}
private function extract(e:Event):void
{
_stream.removeEventListener(ProgressEvent.PROGRESS, showProgress);
_stream.removeEventListener(Event.COMPLETE, extract);
_zipFile = new ZipFile(_stream);
extractFile(0);
}
private function extractFile(id:int):void
{
var applicationDirectory:File = File.applicationDirectory;
var filePath:String;
var zipEntry:ZipEntry;
zipEntry = ZipEntry(_zipFile.entries[id]);
filePath = applicationDirectory.nativePath.toString();
filePath += ("/" + _directory + zipEntry.name);
_currentFile = zipEntry.name;
var storage:File = new File(filePath);
if (zipEntry.name.charAt(zipEntry.name.length - 1) == '/')
{
storage.createDirectory();
}
else
{
var entry:FileStream = new FileStream();
entry.open(storage, FileMode.WRITE);
entry.writeBytes(_zipFile.getInput(zipEntry));
entry.close();
}
dispatchEvent(new ProgressEvent(UNPACK_FILE));
if (id >= _zipFile.entries.length - 1) dispatchComplete();
else setTimeout(extractFile, 50, (id + 1));
}
}
}
Example
Here’s an example of how the class can be used in order to display Progress:
package
{
import com.firsara.utils.Unpacker;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.display.Sprite;
import flash.text.TextField;
public class Main extends Sprite
{
private const ZIP_PATH:String = "http://nochump.com/blog/wp-content/uploads/2008/11/nochump-ziplib-105-src.zip";
private const OUTPUT_DIR:String = "_nochump_src/";
private var unpacker:Unpacker;
private var output:TextField;
public function Main()
{
if (stage) construct();
else this.addEventListener(Event.ADDED_TO_STAGE, construct);
}
private function construct(event:Event = null):void
{
if (event) this.removeEventListener(Event.ADDED_TO_STAGE, construct);
output = new TextField();
output.width = this.stage.stageWidth - 100;
output.height = this.stage.stageHeight - 100;
output.x = output.y = 50;
addChild(output);
unpacker = new Unpacker(OUTPUT_DIR);
unpacker.addEventListener(ProgressEvent.PROGRESS, showProgress);
unpacker.addEventListener(Unpacker.UNPACK_FILE, showUnpack);
unpacker.addEventListener(Event.COMPLETE, unpackComplete);
unpacker.unpack(ZIP_PATH);
}
private function showProgress(event:ProgressEvent):void
{
var p:String = String(Math.round(unpacker.percentage * 100));
if (p.length == 1) p = "0" + p;
output.text = "Unpacking " + p + "%";
}
private function showUnpack(event:ProgressEvent):void
{
output.text = "Unpacking file \"" + unpacker.currentFile + "\"";
}
private function unpackComplete(event:Event):void
{
output.text = "Unpacking in \"" + unpacker.directory + "\" done ";
unpacker.removeEventListener(ProgressEvent.PROGRESS, showProgress);
unpacker.removeEventListener(Unpacker.UNPACK_FILE, showUnpack);
unpacker.removeEventListener(Event.COMPLETE, unpackComplete);
}
}
}
Download
Download the full class including a simple example of how it can be used: UnpackerSample.zip
Note that this class will only work in AIR as it uses “File” and “FileStream”!
If you are able to use this class in your projects please give me credits!
What do you think about this class?
Follow Me!