Skip to content

Instantly share code, notes, and snippets.

@alumican
Last active December 29, 2015 00:28
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alumican/7585773 to your computer and use it in GitHub Desktop.
Save alumican/7585773 to your computer and use it in GitHub Desktop.
zipファイルをダウンロードしてメモリ上に非同期展開するクラス
/**
* zipファイルをダウンロードしてメモリ上に非同期展開する
*
* var loader:ZipLoader = new ZipLoader();
* loader.addEventListener(ZipLoaderEvent.COMPLETE, completeHandler);
* loader.addEventListener(ZipLoaderEvent.ERROR, errorHandler);
* loader.addEventListener(ZipLoaderEvent.EXECUTED, executedHandler);
* loader.load("http://path_to.zip");
*
* function completeHandler(event:ZipLoaderEvent):void {
* trace("成功");
*
* //ダウンロードしたzip内のファイルパス一覧
* trace(loader.paths);
*
* //中身を取得する
* var textBytes:ByteArray = loader.getData("path/to/text.txt");
* var text:String = textBytes.readUTFBytes(textBytes.length);
*
* var imageBytes:ByteArray = loader.getData("path/to/image.png");
* var image:Loader = new Loader();
* image.loadBytes(imageBytes);
*
* var soundBytes:ByteArray = loader.getData("path/to/sound.mp3");
* var sound = new Sound();
* sound.loadCompressedDataFromByteArray(soundBytes, soundBytes.length);
*
* //メモリの破棄(上記のByteArrayも削除されるので参照を保持している場合は注意)
* //loader.dispose();
* }
*
* function errorHandler(event:ZipLoaderEvent):void {
* trace("失敗");
* }
*
* function executedHandler(event:ZipLoaderEvent):void {
* trace("成功でも失敗でも最後に呼ばれる");
* }
*/
package ziploader
{
import com.coltware.airxzip.ZipEntry;
import com.coltware.airxzip.ZipEvent;
import com.coltware.airxzip.ZipFileReader;
import flash.events.ErrorEvent;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.SecurityErrorEvent;
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import flash.net.URLRequest;
import flash.utils.ByteArray;
import flash.utils.getTimer;
import starling.events.EventDispatcher;
/**
* zipファイルをダウンロードしてメモリ上に展開する
*/
public class ZipLoader extends EventDispatcher
{
//----------------------------------------------------------
//
// Constructor
//
//----------------------------------------------------------
public function ZipLoader():void
{
_datasByPath = new Object();
_paths = new Vector.<String>();
_isLoaded = _isLoading = false;
}
//----------------------------------------------------------
//
// Property
//
//----------------------------------------------------------
//--------------------------------------
// isLoaded
//--------------------------------------
private var _isLoaded:Boolean;
public function get isLoaded():Boolean
{
return _isLoaded;
}
//--------------------------------------
// isLoading
//--------------------------------------
private var _isLoading:Boolean;
public function get isLoading():Boolean
{
return _isLoading;
}
//--------------------------------------
// paths
//--------------------------------------
private var _paths:Vector.<String>;
/**
* zip内のファイルパス配列
*/
public function get paths():Vector.<String>
{
return _paths;
}
/**
* @private
*/
private var _datasByPath:Object;
private var _file:File;
private var _fileStream:FileStream;
private var _loader:URLLoader;
private var _queue:Vector.<ZipEntry>;
private var _reader:ZipFileReader;
//----------------------------------------------------------
//
// Function
//
//----------------------------------------------------------
/**
* インスタンスを破棄する
*/
public function dispose():void
{
if (_loader)
{
try
{
_loader.removeEventListener(flash.events.Event.COMPLETE, _loaderCompleteHandler);
_loader.removeEventListener(IOErrorEvent.IO_ERROR, _loaderErrorHandler);
_loader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, _loaderErrorHandler);
_loader.data = null;
_loader.close();
}
catch (error:Error)
{
}
_loader = null;
}
if (_file)
{
try
{
_file.deleteFile();
}
catch (error:Error)
{
}
_file = null;
}
if (_fileStream)
{
try
{
_fileStream.removeEventListener(flash.events.Event.CLOSE, _fileStreamCloseHandler);
_fileStream.removeEventListener(IOErrorEvent.IO_ERROR, _fileStreamErrorHandler);
_fileStream.close();
}
catch (error:Error)
{
_fileStream = null;
}
}
if (_reader)
{
try
{
_reader.removeEventListener(ZipEvent.ZIP_DATA_UNCOMPRESS, _readerZipDataUncompressHandler);
_reader.close();
}
catch (error:Error)
{
}
_reader = null;
}
if (_datasByPath)
{
for each (var data:ByteArray in _datasByPath)
data.clear();
_datasByPath = null;
}
_paths = null;
_queue = null;
_isLoaded = false;
_isLoading = false;
}
/**
* 解凍されたファイルを取得する
*/
public function getData(path:String):ByteArray
{
return _datasByPath[path];
}
/**
* zipファイルを読み込む
*/
public function load(url:String):void
{
//trace("[ZipLoader] Load, url = " + url);
dispose();
_datasByPath = new Object();
_paths = new Vector.<String>();
_isLoaded = false;
_isLoading = true;
//zipファイルをURLから読み込む
_loader = new URLLoader();
_loader.addEventListener(flash.events.Event.COMPLETE, _loaderCompleteHandler);
_loader.addEventListener(IOErrorEvent.IO_ERROR, _loaderErrorHandler);
_loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, _loaderErrorHandler);
_loader.dataFormat = URLLoaderDataFormat.BINARY;
_loader.load(new URLRequest(url));
}
/**
* zipファイルの読み込み完了ハンドラ
*/
private function _loaderCompleteHandler(event:flash.events.Event):void
{
//zipバイナリを一時ファイルとして保存
_file = File.applicationStorageDirectory.resolvePath("tmp_" + getTimer() + ".zip");
_fileStream = new FileStream();
_fileStream.addEventListener(flash.events.Event.CLOSE, _fileStreamCloseHandler);
_fileStream.addEventListener(IOErrorEvent.IO_ERROR, _fileStreamErrorHandler);
_fileStream.openAsync(_file, FileMode.WRITE);
_fileStream.writeBytes(_loader.data);
_fileStream.close();
}
/**
* zipファイルの読み込みエラーハンドラ
*/
private function _loaderErrorHandler(event:ErrorEvent):void
{
_error("URLLoader, " + event);
}
/**
* 一時ファイルの書き込み完了ハンドラ
*/
private function _fileStreamCloseHandler(event:flash.events.Event):void
{
_loader.data = null;
//zipファイルマネージャを作成
_reader = new ZipFileReader();
//zipファイルかどうかチェック
if (!_reader.check(_file))
{
_error("FileStream, file is not zip");
return;
}
//zipに含まれるファイルリストを抽出
_reader.open(_file);
_queue = Vector.<ZipEntry>(_reader.getEntries());
//解凍を開始
_datasByPath = new Object();
_reader.addEventListener(ZipEvent.ZIP_DATA_UNCOMPRESS, _readerZipDataUncompressHandler);
_reader.unzipAsync(_queue.pop());
}
/**
* 一時ファイルの書き込みエラーハンドラ
*/
private function _fileStreamErrorHandler(event:ErrorEvent):void
{
_error("FileStream, " + event);
}
/**
* zipファイルの解凍ハンドラ
*/
private function _readerZipDataUncompressHandler(event:ZipEvent):void
{
//解凍したファイルをメモリに保持
var path:String = event.entry.getFilename();
_datasByPath[path] = event.data;
_paths.push(path);
//trace("[ZipLoader] Uncompressed : " + path);
if (_queue.length > 0)
{
//次のデータを読み込む
_reader.unzipAsync(_queue.pop());
}
else
{
//全てのファイルを解凍完了
_file.deleteFileAsync();
_reader.removeEventListener(ZipEvent.ZIP_DATA_UNCOMPRESS, _readerZipDataUncompressHandler);
_isLoaded = true;
_isLoading = false;
//trace("[ZipLoader] Complete");
dispatchEvent(new ZipLoaderEvent(ZipLoaderEvent.COMPLETE));
dispatchEvent(new ZipLoaderEvent(ZipLoaderEvent.EXECUTED));
}
}
/**
* エラー処理
*/
private function _error(errorMessage:String):void
{
dispose();
_datasByPath = new Object();
_isLoaded = false;
_isLoading = false;
trace("[ZipLoader] Error : " + errorMessage);
dispatchEvent(new ZipLoaderEvent(ZipLoaderEvent.ERROR));
dispatchEvent(new ZipLoaderEvent(ZipLoaderEvent.EXECUTED));
}
}
}
package ziploader
{
import starling.events.Event;
/**
* ZipLoaderによって発行されるイベント
*/
public class ZipLoaderEvent extends Event
{
//----------------------------------------------------------
//
// Static Property
//
//----------------------------------------------------------
/**
* 解凍に完了したときに発行される
*/
public static const COMPLETE:String = "ZipLoaderEvent.COMPLETE";
/**
* 解凍に失敗したときに発行される
*/
public static const ERROR:String = "ZipLoaderEvent.ERROR";
/**
* 成否にかかわらず解凍が終了したときに発行される
*/
public static const EXECUTED:String = "ZipLoaderEvent.EXECUTED";
//----------------------------------------------------------
//
// Constructor
//
//----------------------------------------------------------
public function ZipLoaderEvent(type:String, bubbles:Boolean = false, data:Object = null):void
{
super(type, bubbles, data);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment