package zip 
{
import com.hurlant.crypto.hash.MD5;
import com.hurlant.util.Hex;
import flash.events.Event;
import flash.events.IOErrorEvent;
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 deng.fzip.FZip;
import deng.fzip.FZipFile;
import flash.utils.Dictionary;

public class ZIPResourceLoader {
    public var resourcesURL:String = "http://127.0.0.1:8000/resources.zip";
	public var md5FilePath:String = File.applicationStorageDirectory.nativePath + File.separator + "123.md5";
    public var localFilePath:String = File.applicationStorageDirectory.nativePath + File.separator + "resources.zip";
    public var zipLoader:URLLoader = new URLLoader();

    public function ZIPResourceLoader() {
        zipLoader.dataFormat = URLLoaderDataFormat.BINARY;
        zipLoader.addEventListener(Event.COMPLETE, onZipLoaded);
        zipLoader.addEventListener(IOErrorEvent.IO_ERROR, onZipLoadError);
        zipLoader.addEventListener(Event.OPEN, onZipLoadStart);
        zipLoader.load(new URLRequest(resourcesURL));
    }

    public function onZipLoadStart(event:Event):void {
        Alert.showMessage("Load resources.zip started!");
    }

public function onZipLoaded(event:Event):void {
    var zipBytes:ByteArray = zipLoader.data;
    var fileStream:FileStream = new FileStream();
    fileStream.open(new File(localFilePath), FileMode.WRITE);
    fileStream.writeBytes(zipBytes);
    fileStream.close();

    // Загрузка ресурсов завершена
    var md5URL:String = "http://127.0.0.1:8000/123.md5";
    var md5Loader:URLLoader = new URLLoader();
    md5Loader.addEventListener(Event.COMPLETE, function(md5Event:Event):void {
        var md5:String = md5Event.target.data;
        var md5Local:String = calculateMD5(localFilePath);

        if (md5 != md5Local) {
            var zipFile:FZip = new FZip();
            zipFile.addEventListener(Event.COMPLETE, onZipExtracted);
            zipFile.loadBytes(zipBytes);
        } else {
            // Если MD5 суммы совпадают, архив на хосте не изменился
            // Выполните здесь необходимые действия
            Alert.showMessage("Resources.zip has not changed");
        }
    });
    md5Loader.addEventListener(IOErrorEvent.IO_ERROR, function(md5Error:IOErrorEvent):void {
        Alert.showMessage("Failed to load resources.zip.md5" + md5Error.toString());
    });
    md5Loader.load(new URLRequest(md5URL));
}

    public function onZipLoadError(event:IOErrorEvent):void {
        Alert.showMessage("Failed to load resources.zip");
    }

public function onZipExtracted(event:Event):void {
    var zipFile:FZip = event.target as FZip;
    try {
        var extractedFiles:Dictionary = new Dictionary();

        for (var i:int = 0; i < zipFile.getFileCount(); i++) {
            var zipEntry:FZipFile = zipFile.getFileAt(i);
            var targetFilePath:String = File.applicationStorageDirectory.nativePath + File.separator + "cache/resources" + File.separator + zipEntry.filename;
            var targetFile:File = new File(targetFilePath);

            extractedFiles[targetFilePath] = true;

            if (zipEntry.filename.charAt(zipEntry.filename.length - 1) == "/") {
                targetFile.createDirectory();
            } else {
                var targetFileStream:FileStream = new FileStream();
                targetFileStream.open(targetFile, FileMode.WRITE);
                targetFileStream.writeBytes(zipEntry.content);
                targetFileStream.close();
            }
        }

        // Удаляем все файлы, которые не были извлечены из архива
        var cacheDir:File = new File(File.applicationStorageDirectory.nativePath + File.separator + "cache/resources");
        var listCacheDir:Array = cacheDir.getDirectoryListing();

        for each (var file:File in listCacheDir) {
            if (!extractedFiles[file.nativePath]) {
                file.deleteFile();
            }
        }

        // Загружаем файл resources.zip.md5
        var md5URL:String = "http://127.0.0.1:8000/resources.zip.md5";
        var md5FilePath:String = File.applicationStorageDirectory.nativePath + File.separator + "resources.zip.md5";
        var md5Loader:URLLoader = new URLLoader();
        md5Loader.addEventListener(Event.COMPLETE, function(md5Event:Event):void {
            var md5:String = md5Event.target.data;
            var md5Local:String = calculateMD5(md5FilePath);

            if (md5 != md5Local) {
                Alert.showMessage("MD5 checksum mismatch");
            } else {
                Alert.showMessage("Resources.zip has not changed");
            }
        });
        md5Loader.addEventListener(IOErrorEvent.IO_ERROR, function(md5Error:IOErrorEvent):void {
            Alert.showMessage("Failed to load resources.zip.md5" + md5Error.toString());
        });
        md5Loader.load(new URLRequest(md5URL));

        Alert.showMessage("Extracted successfully!");
    } catch (error:Error) {
        Alert.showMessage("Failed to extract resources.zip: " + error.message + " (" + error.errorID + ")");
    }
}
    
    private function calculateMD5(filePath:String):String {
        var file:File = new File(filePath);
        var fileStream:FileStream = new FileStream();
        fileStream.open(file, FileMode.READ);
        var fileBytes:ByteArray = new ByteArray();
        fileStream.readBytes(fileBytes, 0, fileStream.bytesAvailable);
        fileStream.close();
        
        var md5Hash:MD5 = new MD5();
        var hashBytes:ByteArray = md5Hash.hash(fileBytes);
        
        return Hex.fromArray(hashBytes);
    }
}
} почему то выдает ошибку 3003, хотя все распаковалось