延续前些日子的问题,我用AIR开发一个断点续传的工具(好像没贴博客上,稍后放出)。我用这个AIR工具下载了一个zip文件,当我下载完成后,我希望通过AIR控制其自动解压压缩包内的文件到我指定的目录下。
这需要用到as3操作zip压缩包数据的方法。
我在网络上搜索了一下前人的操作zip相关类包,比如ZIPArchive、fzip、ZIPer(Y.Boy)、Fzlib,发现这些类包虽然定义了比如读取zip内部文件、将文件打包为zip的方法,但是对于读取zip数据后,怎样将这些数据转化为操作系统中的实际文件都没有给出实际方法(或者我没有理解透彻)。
其实也不怪这些位大大们,他们都给出了获得文件的ByteArray的方法,那么只要操作这些ByteArray就可以生成相应的实际文件,这都是flash自己的方法。我写这篇教程要讲的就是这后续实际要做的工作,即如何真实的将zip压缩包解压。
注意:本文使用了ZIPArchive类包,这个类包应该是位国人所写,此类包下载参考http://code.google.com/p/as3-ziparchive/,当然用其他类包也是可以实现的,只需要用他们的读取zip中BytesArray的方法即可。
步骤:http://hi.baidu.com/taotao5453
1、首先,使用Flash?CS3或CS4创建一个新的flash?AIR工程。工程目录如下,如图1,文件夹“riaidea”就是上面下载的ZIPArchive类包;example_me.fla是新建的AIR工程的主文件,它的文档类填写“Example”;Example.as就是.Fla的文档类;test.zip是一会要操作解压的类,它的内部一共有三个文件,分别是.jpg、.gif、.xml格式,如图2。
(图1):
(图2):
2、Example.as类
在这里可以看到,我们之所以创建AIR工程,是为了使用AIR的相关API:File、?FileStream、?FileMode,用来操作系统中的文件,普通的flash?CS工程是不能使用的。
package?{
import?flash.display.Bitmap;
import?flash.display.Sprite;
import?flash.events.ProgressEvent;
import?flash.utils.ByteArray;
import?flash.events.Event;
import?flash.events.IOErrorEvent;
import?riaidea.utils.zip.ZipArchive;
import?riaidea.utils.zip.ZipEvent;
import?riaidea.utils.zip.ZipFile;
import?flash.filesystem.File;//AIR?only
import?flash.filesystem.FileMode;//?AIR?only
import?flash.filesystem.FileStream;//?AIR?only
public?class?Example?extends?Sprite?{
private?var?zip1:ZipArchive?=?new?ZipArchive();
public?function?Example()?{
//加载一个zip档案
zip1.load("test.zip");
zip1.addEventListener(ProgressEvent.PROGRESS,?loading);
zip1.addEventListener(ZipEvent.ZIP_INIT,?inited);
zip1.addEventListener(ZipEvent.ZIP_FAILED,?failed);
zip1.addEventListener(IOErrorEvent.IO_ERROR,?ioError);
}
private?function?inited(evt:ZipEvent):void?{
zip1.removeEventListener(ProgressEvent.PROGRESS,?loading);
zip1.removeEventListener(ZipEvent.ZIP_INIT,?inited);
zip1.removeEventListener(ZipEvent.ZIP_FAILED,?failed);
/******以下用来操作解压zip*******/
var?len:int?=?zip1.length;
for(var?i=0;?i<len;?i++){
var?newZipFile:ZipFile?=?zip1.getFileAt(i);
var?byteArray:ByteArray?=?new?ByteArray();
byteArray?=?newZipFile.data;
var?fileStr:FileStream?=?new?FileStream();
var?file:File?=?new?File("d:/temp/"?+?newZipFile.name);//创建新的File方便后面向File写入数据
fileStr.open(file,?FileMode.UPDATE);//以更新形式打开文件,准备更新
fileStr.position?=?fileStr.bytesAvailable;//将指针指向文件尾
fileStr.writeBytes(byteArray,?0,?byteArray.length);//在文件中写入新下载的数据
fileStr.close();//关闭文件流
}
}
private?function?loading(evt:ProgressEvent):void?{
//trace(evt.currentTarget,?evt.bytesLoaded,?evt.bytesTotal);
}
private?function?failed(evt:ZipEvent):void?{
//trace(evt.content);
}
private?function?ioError(evt:IOErrorEvent):void?{
//trace(evt);
}
}
3、对example_me.fla使用Crtl+Enter调试,我们就可以在d:/temp/下找到解压出来的三个文件了,即成功!
4、说明:ZIPArchive类包中还有ZIPArchive的addFileFromString、getBitmapByName、removeFileByName方法可以操作压缩包内的文件。我正在试验如何解压内部带文件夹的zip,我想上面的Example.as可能需要完善一下,文章先发到这里了!!http://hi.baidu.com/taotao5453
********************
********************
经测试,以下方法对有文件夹的zip压缩包也有效,一个文件如果是在压缩包的一个文件夹里,那么当取它的newZipFile.name名字时是带路径的名字,例如sample123/logo.gif,在使用?fileStr.open(file,?FileMode.WRITE);?时会自动先创建文件上一级的文件夹,然后在生成文件logo.gif。
(使用以下方法替换inited方法中的for循环即可):
for(var?i=0;?i<len;?i++){ var?newZipFile:ZipFile?=?zip1.getFileAt(i); var?byteArray:ByteArray?=?new?ByteArray(); byteArray?=?newZipFile.data;?var?fileStr:FileStream?=?new?FileStream(); var?file:File?=?new?File;//C:Documents?and?Settingsusername file?=?file.resolvePath("D:/temp/"?+?newZipFile.name); trace(newZipFile.name);?if(file.isDirectory?==?false){?//判断是否为文件夹,不是文件夹时候向下进行,按照文件的目录结构依次生成文件夹、文件 fileStr.open(file,?FileMode.WRITE);?//以写形式打开文件,准备更新?fileStr.writeBytes(byteArray,?byteArray.length);?//在文件中写入新下载的数据 fileStr.close();//关闭文件流 }else{?} }