Here’s an ActionScript 3 based library for reading and writing zip files. I wrote this for another project I’m messing around with and thought I’d release it. I realize there’s already a useful library out there called FZip which is faster at uncompressing zip files as it uses the native uncompress method. However, it may require a script to preprocess a zip and inject Addler32 checksums which this library avoids by implementing a deflate compression decoder (inflater). If you are dealing with zips that only store files or run Python I recommend you check out FZip otherwise give this a try.
Features
- Read or write zip files
- Interface based on Java API (java.util.zip package)
Demo
The source for this demo is available here.
Documentation
Download
The zip library is available as a swc component:
nochump-ziplib-105-dist.zip
The source files and documentation are also available:
nochump-ziplib-105-src.zip
License
MIT
Usage
Below are examples of reading from a zip and writing to a new zip.
// read from a zip
import flash.utils.IDataInput;
import nochump.util.zip.*;
var loadedData:IDataInput;
// load a zip via URLStream or URLLoader using binary data format...
// create zip file
var zipFile:ZipFile = new ZipFile(loadedData);
for(var i:int = 0; i < zipFile.entries.length; i++) {
var entry:ZipEntry = zipFile.entries[i];
trace(entry.name);
// extract the entry's data from the zip
var data:ByteArray = zipFile.getInput(entry);
trace(data.toString());
}
// write to a new zip
import flash.utils.ByteArray;
import nochump.util.zip.*;
// file info
var fileName:String = "helloworld.bin";
var fileData:ByteArray = new ByteArray();
fileData.writeUTF("Hello World!");
var zipOut:ZipOutput = new ZipOutput();
// Add entry to zip
var ze:ZipEntry = new ZipEntry(fileName);
zipOut.putNextEntry(ze);
zipOut.write(fileData);
zipOut.closeEntry();
// end the zip
zipOut.finish();
// access the zip data
var zipData:ByteArray = zipOut.byteArray;
Update: April 11, 2007
Updated the library to use Apollo’s ByteArray inflate/deflate native methods when running in the Apollo environment as pointed out by Ian Thomas. The current version is 1.0.1 built with acompc from the Apollo SDK. I’ve also tested the Apollo compatible swc under a regular as3 app and everything worked fine.
Update: July 29, 2007
Supports adding a zip file comment to ZipOutput. Use ZipOutput.comment =”Your comment here”.
Update: January 28, 2008
Changed license to LGPL.
Update: November 22, 2008
Changed license to MIT.
2 Trackbacks
[...] app is a desktop app, so that’s not necessarily a showstopper) or to use David Chang’s nochump.util.zip library, which is pure AS3 … Subscribe to comments Comment | Trackback | Share [...]
[...] AS3 Zip Library Release (nochump.com) [...]
73 Comments
The site looks great ! Thanks for all your help ( past, present and future !)
Thank you!
Hi Dave,
Just a quick note – with Apollo, you get inflate() and deflate() support for free (natively), as new methods of ByteArray.
It might be worth modifying your code to check whether the methods exist on ByteArray, then call them instead of your own if they’re present?
For example, in ZipFile.as at around line 100, you could add:
if (b1.inflate!=null)
{
b1.inflate();
return b1;
}
and you could do exactly the same in ZipOutput.
Cheers,
Ian
Hey Ian,
That’s a great tip, I’ll definitely have to update this zip library to support it. Thanks!
Hey Dave, this is a really great library. Works very well, and very quickly in Apollo.
Question though – Have you considered changing the license to use LGPL instead of GPL?
I am not a public license expert, but I believe the GPL is too restrictive to use for most commercial projects. (Thats cool if that is your intent!)
Cheers,
-D
Thanks Daniel, well I don’t know much about public licenses myself. The reason I went with GPL was that the java source and GNU Classpath are both release under it. Though this library is not a direct port of those, I did look to them for the interface, their supported zip features, and some general ideas. So to play it safe, and out of convenience, I went with the same. However, there was an exception in GNU Classpath’s license that appears to deal with your situation. Would it help you out to add that to this library?
Anyways, I want things to be flexible for the non-commercial developer as well as the commercial. So if that exception doesn’t make it less restrictive, I’m really open to the idea of changing the license to LGPL or some other one. Lemme know
Hi David,
great work, thank you !
I’m using it to load a 600kb XML-File.
After “zipping” my File has only 8kb. So the start of my application is MUCH faster.
Greetings from Berlin,
Uwe
I am attempting to use your create zip example with a slight modification
http://codeshare.ulatu.com/julff076
The zip file created is 14kb, but when I open it. the file inside is 0 bytes.
Even if I use your example as it is shown, the HelloWorld.bin file is 0 bytes.
Any suggestions would be greatly appreciated.
Critter
This projects sounds great. Congratulations.
Should it read a pass protected zip when providing de correct password?
It would be a way to protect data…
Thanks
Hey Critter,
Sorry for the long delay getting back to you. Anyways I finally had the chance to look into this and the issue was in the way the entry data gets compressed under AIR…there was nothing wrong with your code. In version 1.0.1, I had tweaked it to support their native ByteArray.deflate method when building under for AIR but for some reason it doesn’t seem compatible so I’ve updated this library reverting back to a previous deflate method. Well long story short, I’ve tested this version writing zipOut.byteArray to a file within an AIR app and reading it back in with ZipFile as well as a desktop ZIP application and was successful. So please give this updated version a try and let me know if you run into any issues.
Thanks for catching this as I really have not had the chance to play with AIR.
Dave
Hey Farid,
Thanks for your comment. I considered this but it was not a feature I needed for the project I originally wrote this library for. Plus, the steps involved for decryption seemed much when I glanced over that section in the zip spec. Would love to tie it in though if anyone wanted to contribute an implementation.
Dave, it totally works now, thanks!!
Great to hear Critter!
Just curious mate. Is it possible to add the ability to manipulate zip file comments?
Hi dchang,
is it possible for you to implement a feature to extract gz files ? I think the only difference to zip is the header. It would be very useful for me.
Thanks
Comments would be easy to add, I’ll try to this weekend. As for gzip support, I’ll look into it. Hopefully it’s as easy as you say
Hey dchang,
Could you post a quick example showing how to zip up multiple folders? I’m not totally sure how’d that’d work w/ the current API. Thanks in advance — Great library.
Hey, good question…to create folders you can simply set the path with the filename when creating a ZipEntry. So with the example above…
var fileName:String = “mysubfolder/helloworld.bin”;
A directory called mysubfolder will be created with the file helloworld.bin inside when extracted.
Typically compressors will put a 0 size entry for each subfolder denoted by a trailing backslash. However, the extractors I’ve used all handled just the path/filename.ext entries alone fine unless you want to make empty folders. If you want to have directory entries anyways, this should do the trick…
var ze:ZipEntry = new ZipEntry(“mydir/”);
zipOut.putNextEntry(ze);
zipOut.closeEntry();
but again, I didn’t find this necessary and preferred less coding and a slightly smaller bytesize.
Awesome, thanks.
hello,
this sounds great,
i have some questions though:
-is it possible to add existing files to the (to be created) zip?
I´d like to add a file (let´s say test.jpg) that is placed in the same folder as the swf on the server to the zip. Is that possible without loading the jpg and turning it into a bytearray first?
-how does one actually save the zip data as file than if not running in apollo? do you have a php file or something to save the data on the server?
Hey there, afraid you’ll have to load the jpg into the swf via binary format but you could then use flash.display.Loader.loadBytes on that ByteArray for displaying so it only loads once. I dunno if that was your concern but without loading the jpg into swf, you might want to go with a server-side zip library.
As for saving the data to the server, I don’t have an example of this but found these links which may help… Save ByteArray to file with PHP or with AMFPHP see Send and Receive ByteArray to AMFPHP.
Great, great, great !!!!!!!!
…you saved me a lot of time. I used your code to import contents of odf files. I thought I have to extend FZip with CRC32 algorithm feature.
Just a detail: The apollo environment settings in ZipFile.as gives an error if not using apollo!
Great job on this, David.
Here’s another vote for switching the license to LGPL or MIT. A lot of people won’t be able to use it under GPL for shareware or commercial apps because GPL requires any app using your library to also be open-source. If that’s your intention, that’s one thing but if you don’t care either way (as you imply in one of your comments) then you might want to switch to one of the other options.
hello, i asked you some things before. Sorry for my late reply, i actually didn´t get to work on the stuff for a while..
But now i did and i wanted to say thanks heaps, it works great
The way i do it now is like this:
In my app i show lots of images so i first load and show all those. Then once all are loaded the user can save a selection of them as a zip. To do this i load em again but this time as bytedata (which goes quickly as they are already in the cache) and then create a zip with subfolders using your code and then save that via php.
I´m not sure if that´s the best way to do things (i mean maybe i could get rid of the second load loop to get the images as byte data and turn the data of the already loaded images into bytedata? not sure how) but yeah, works fine
Thank you!
great work!
Fantastic package. Reads every zip file!
I use it to load 3D data stored in an xml file which is know zipped.
So I only need to load 28kb instead of ther original 470kb.
It’s amazing!
Well done…
Hello, Great Library……
I tried using this library…. reading a zip file works fine…
But i am not able to create a new zip file and put multiple files of different types(xml, jpg etc.)in to it and save it to the local disk….
Please help me somone who has alredy done this..
Thanks in advance….
naren
I got ‘unexpected file format’ when I want to install SWF in to Flash CS3.
Anyone had this issue?
Hi, great job!
FZip library doesn’t uncompress zip files with data description blocks but YOUR LIBRARY DO IT WELL.
Thanks! It was helpful for me.
Hi Dave,
what about extracting Zip Files protected by PassWord?
Thank You!
Dave,
Does this work for Flex Builder 3? I downloaded the source and swc and tried to integrate and getting the below error:
Error: invalid zip
at nochump.util.zip::ZipFile/findEND()[E:\FlexWorkSpace\flex\LWWDashboard\src\nochump\util\zip\ZipFile.as:187]
at nochump.util.zip::ZipFile/readEND()[E:\FlexWorkSpace\flex\LWWDashboard\src\nochump\util\zip\ZipFile.as:170]
at nochump.util.zip::ZipFile/readEntries()[E:\FlexWorkSpace\flex\LWWDashboard\src\nochump\util\zip\ZipFile.as:124]
at nochump.util.zip::ZipFile()[E:\FlexWorkSpace\flex\LWWDashboard\src\nochump\util\zip\ZipFile.as:51]
at LWWDashboard/onZipLoaded()[E:\FlexWorkSpace\flex\LWWDashboard\src\LWWDashboard.mxml:26]
Any Idea what could be wrong?
Vipin
Can this be used to load png files also? Maybe an example if it does. Thanks, and great work!
Dave, thanks for this component. It saved me a lot of time writing my own.
I encountered a problem with reading “non-zips”. My application can read certain custom files that can be zipped or not. I wrote the code to attempt to open the file with your component, and if it exceptioned then I assume it’s not a zip and read it in an alternate way. However, I ran into a problem with your ZipFile.findEND function where it would go into an infinite loop if n = 0 and it didn’t encounter the signature it was looking for. Apprently, you knew about it since there’s a TODO. I just thought that I would share my fix. Basically, I added && (i != uint.MAX_VALUE) to the for statement. Here’s the code.
private function findEND():uint {
var i:uint = buf.length – ZipConstants.ENDHDR;
var n:uint = Math.max(0, i – 0xffff); // 0xffff is max zip file comment length
// TODO: issue when n is 0 and ENDSIG not found (since variable i cannot be negative)
//–Temp fix: Added i != uint.MAX_VALUE
for(i; i >= n && i != uint.MAX_VALUE; i–) {
if(buf[i] != 0×50) continue; // quick check that the byte is ‘P’
buf.position = i;
if(buf.readUnsignedInt() == ZipConstants.ENDSIG)
return i;
}
throw new ZipError(“invalid zip”);
return 0;
}
Personally, I think you should have a routine called something like “CheckZipSignature” that will read the first four bytes and check them against the zip signature and call that routine from the constructor and then exception out right away. A static utility function called isZipFile(input IDataInput):Boolean would be cool as well.
Thanks again for this component. It works very well.
Mr. Chang,
Thanks for making this available. Unfortunately, I now have need for a RAR library. Have you given any thought to creating Actionscript that can unrar files? I’d try myself, but I am crap at Bit coding!
Leif
Atlanta
I have used your library to create and unpack zip files
there is only 1 limitation i have.
when i create a zip file with your api and i add some FLV’s bytearray code to it goes SUPER fast.
but when i want to unpack that zip (and let say just write it to the disk ( with air )) the inflater takes about 30 times longer to do that.
is this a bug or something ? i would think IF it would slow down it would be the other way around.
i’ve tested it with an 8mb FLV and to unpack it takes 61 SECONDS in comparison to zip it it takes 3seconds
greetings
Andy
Hi,
thank you, great work!
Your first example didn’t work if filenames start with a point.
So I have to change it like this:
...
if( !entry.name.search('/\.') ){
// extract the entry's data from the zip
var data:ByteArray = zipFile.getInput(entry);
trace(data.toString());
}
...
Uh – delete my last comment, please.
In 1.0.4 works every thing fine…
cool stuff!
great library! having trouble setting it up so the zip file created is simply using the store method. Any help?? I’ve set the parameter method in the zipentry to 0 instead of -1. but, i keep getting crc errors or the files are empty. any ideas?? many thanks.
Help, I’m getting : Error: distance is too far back in fixed or dynamic block
can anyone else share me their working code to uncompress a file using FLEX? thanks so much. .
Stevenc@steves-imports.com
Hi there!
Tell me, is there a way to get rar files to work with it?
Thanks!
I have a question. Is it possible to save this byteArray as zip file using FileReference.save()? When I try to do this – I always get crush. Perhaps this is because the flash player is still beta…
…. (same as example)
var zipData : ByteArray = zipOut.byteArray;
var fr : FileReference = new FileReference();
fr.save(zipData, “test.zip”);
Hi Dave,
I had a problem when i add a file which named by chinese. And than, I checked your source code, but no can resolve it. So~
Thank You very much.
Hi!,
Thanks!
simple & clear.
regards
Hi,
Are there any new updates to this SWC in 2008? Is development continuing or is the version listed here the latest/greatest?
When using this library with larger zip files, you get script timeout errors in the inflater code loop. Might be nice if the library switched to using fake thread timers to stagger the execution of an unzip and then dispatch events as progress/complete/error occurs.
Hi,
I’m attempting to load a non-zip file (a .gif), but the application doesn’t throw any error. It gets stuck in the for loop at the function findEND():uint in “ZipFile.as”. I think you already know this problem, because there’s a comment here:
// TODO: issue when n is 0 and ENDSIG not found (since variable i cannot be negative)
What’s the point of loading a .gif file with the AS3 zip lib ? None. If it happens, that would be a human error. But I don’t want the app to hang of course, I want to be able to display a message to the user that this is not a zip file and continue. Any idea how this could be fixed ?
Regards,
Alex
Hi,
I made a quick workaround: if var “i” equals 4294967295, chances are that i went from 0 to 4294967295 since “i” can’t be negative.
for(i; i >= n; i–) {
+ if(n == 0 && i == 4294967295) break;
if(buf[i] != 0×50) continue; // quick check that the byte is ‘P’
Regards,
Alex Conrad
Hi,
I am having problem in unzipping ZIP file containing file having name with Multi-Byte character like Japanese characters.
zipFile.getInput(entry) throws error “error while decompressing”
Please help me in this regard???
Thank you,
Deepak
Hi,
How can we zip a folder that contains files? Is anyone having any sample for implementing the same?
Hi,
I am facing problem while creating a zip of folder.If anyone has done this please help me out.
hi!
i am using your zip library to import the content of KMZ files into google maps. Occasionally some of these files appear to be damaged. According to WinRAR this is due to an ‘Unexpected end of archive’.
When creating a ZipFile in Flash trying to load a damaged KMZ file this leads to the following error and the application won’t respond for 15 seconds.
that’s my code:
var data:URLStream = URLStream(event.target);
var zip:ZipFile = new ZipFile(data);
and that’s the error message:
Error: Error #1502: A script has executed for longer than the default timeout period of 15 seconds.
at nochump.util.zip::ZipFile/findEND()
at nochump.util.zip::ZipFile/readEND()
at nochump.util.zip::ZipFile/readEntries()
at nochump.util.zip::ZipFile()
How can I prevent this error from arising? I already check URLStream for bytesAvailable which return i.e. 9696. Since the error occurs when creating a new ZipFile I’d either have to check beforehand if it is a valid file (not sure how to do this?), or I’d have to extend your source code. Do you have any idea how I can solve this problem?
thanks,
cyrt
Thanks.
How I can get BtmapData from ByteArray (after “zipFile.getInput(entry);”)?
Hi very great lib
But my requirement is to do zip and not to load a zip file. i want to do it in flex so give me a idea how to implement it in flex to compress files in to zip.
Hi, great job. Thank you for your library.
A problem is when I use getInput(entry) of ZipFile class, it takes a long time to get byte array of a file (5 MB).
Then I change code like following :
case ZipConstants.DEFLATED:
var b2:ByteArray = new ByteArray();
var inflater:Inflater = new Inflater();
inflater.setInput(b1);
inflater.inflate(b2);
return b2;
- to –
case ZipConstants.DEFLATED:
b1.uncompress.apply(b1, ["deflate"]);
return b1;
It is faster.
Thank you again for your library
Hi,
I have Error #1000 Out of memory when reading a large zip file ( about 600 MB). It comes from the ZipFile constructor : data.readBytes(buf);
I think the data stream is too large, so the Byte Array is overflow.
I need your help.
Thanks
I want to create a new zip file and put multiple files of different types(xml, jpg,xslt etc.)in to it and save it to the local disk….
Please suggest .
Great! Thanks a lot. but if it can uncopress GZIP format data in memory? which returned from a http server?
Great! I wonder if it can decompress gzip data in memory?
Hi,
I have not been able to extract a mac executable (.app) file and have it successfully maintain the permissions. Can anyone point me in a direction to take with regards to modifying the library?
Cheers
Your control is great. I think I found a bug though. I’m creating a zip file and if you don’t set the ZipEntry date it will get set to the current date and time. This date and time is off by a couple of days. The time is correct though. I also tried to set it to a fixed date as a test and it’s still off. I suspect there’s a problem with converting to “dostime”, but I can’t seem to find any documentation on that.
I’m hoping you might have an idea on how to fix it.
Hey, I just found the problem inside ZipEntry.time you look at Date.day instead of Date.date.
Hey!
I am compiling my code with the newly released Flex sdk 3.5 and I am getting errors about “The supplied index is out of bounds”
here is the stack trace it gives me:
RangeError: Error #2006: The supplied index is out of bounds.
at flash.utils::ByteArray/writeBytes()
at nochump.util.zip::Deflater/deflate()[/Users/dchang/Projects/workspaces/nochump/zip/src/nochump/util/zip/Deflater.as:80]
at nochump.util.zip::ZipOutput/write()[/Users/dchang/Projects/workspaces/nochump/zip/src/nochump/util/zip/ZipOutput.as:124]
can you please fix? i am kinda using this for a project and if it doesn’t work I am not sure what I am going to do, as we need zip files :3
sorry, I fixed my problem, it was your code that was throwing the error, but it was because my xml stuff was of length 0 or something….yeah.
…except password protected archives, right? Still not supported… ffs
Hi,
It’s possible compress multiple files into one archive? Can I have an example of this application?
I cerated a function using the code provided. My zip file is in a URL (e.g. myFolder\…\myZip.zip). How can pass the URL to the function?
Anyone can help? Thanks.
——————–
import flash.utils.IDataInput;
import nochump.util.zip.*;
// read from a zip
public function unZip() {
var loadedData:IDataInput;
// load a zip via URLStream or URLLoader using binary data format…
// create zip file
\var zipFile:ZipFile = new ZipFile(loadedData);
for(var i:int = 0; i < zipFile.entries.length; i++) {
var entry:ZipEntry = zipFile.entries[i];
trace(entry.name);
// extract the entry’s data from the zip
var data:ByteArray = zipFile.getInput(entry);
trace(data.toString());
}
}
i have just come across this site and cannot figure out how you’d zip a folder and then access that zip, could you please post a sample?
Thanks
When I use the compression code for the second time then there is a error of duplicate entry (it works fine for the first time). I explicitly allocate and deallocate memory to the variable in the code . Well compression for the first time works really fine and smoothly.
amazing!good article
Es o maior
I have tried to load a zip into flash with this library on a server environment and flash won’t even give me a progress event..
But locally it works just fine.. is this a limitation of flash??