Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/actionscript-3/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/flash/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Actionscript 3 AIR(As3)-通过iPad应用程序下载大文件_Actionscript 3_Flash_Mobile_Air - Fatal编程技术网

Actionscript 3 AIR(As3)-通过iPad应用程序下载大文件

Actionscript 3 AIR(As3)-通过iPad应用程序下载大文件,actionscript-3,flash,mobile,air,Actionscript 3,Flash,Mobile,Air,首先,我想指定我不能发布源代码,因为这个项目太大了。 我正试图在iPad设备上下载一个大文件(500+MB)。 起初我尝试使用URLLoader,但后来我意识到iPad设备的内存资源非常有限。我原以为URLStream会将文件分块下载,使用FileStream我可以将这些分块保存在设备上(如下所示),但我错了,当我尝试下载一个大文件时,设备崩溃,因为设备的RAM不够(更确切地说,这会变得太大:System.privateMemory) 有人知道如何分块下载文件吗?不使用“套接字连接”也可以吗 提

首先,我想指定我不能发布源代码,因为这个项目太大了。 我正试图在iPad设备上下载一个大文件(500+MB)。 起初我尝试使用URLLoader,但后来我意识到iPad设备的内存资源非常有限。我原以为URLStream会将文件分块下载,使用FileStream我可以将这些分块保存在设备上(如下所示),但我错了,当我尝试下载一个大文件时,设备崩溃,因为设备的RAM不够(更确切地说,这会变得太大:System.privateMemory) 有人知道如何分块下载文件吗?不使用“套接字连接”也可以吗

提前谢谢

编辑: 下面是我使用的代码(注释行是仅在下载文件后关闭FileStream las的版本)



    package components.streamDownloader
    {
        import flash.events.Event;
        import flash.events.EventDispatcher;
        import flash.events.IOErrorEvent;
        import flash.events.OutputProgressEvent;
        import flash.events.ProgressEvent;
        import flash.events.SecurityErrorEvent;
        import flash.filesystem.File;
        import flash.filesystem.FileMode;
        import flash.filesystem.FileStream;
        import flash.net.URLRequest;
        import flash.net.URLStream;
        import flash.system.System;
        import flash.utils.ByteArray;


    /**
     * 
     */
    public class StreamDownloader extends EventDispatcher
    {

        [Event(name="DownloadComplete", type="com.tatstyappz.net.DownloadEvent")]

        [Event(name="Error", type="com.tatstyappz.net.DownloadEvent")]


        //--------------------------------------------------------------------------
        //
        //  Constructor
        //
        //--------------------------------------------------------------------------

        public function StreamDownloader()
        {

        }


        //--------------------------------------------------------------------------
        //
        //  Variables
        //
        //--------------------------------------------------------------------------

        private var file:File;

        //private var fileStream:FileStream;

        private var urlRequest:URLRequest;

        private var urlStream:URLStream;

        private var waitingForDataToWrite:Boolean = false;


        //--------------------------------------------------------------------------
        //
        //  API
        //
        //--------------------------------------------------------------------------

        public function download(urlRequest:URLRequest, file:File):void {


            init();

            this.urlRequest = urlRequest;
            this.file = file;
            //fileStream.open(file, FileMode.WRITE);
            urlStream.load(urlRequest);
        }   


        //--------------------------------------------------------------------------
        //
        //  Event handlers
        //
        //--------------------------------------------------------------------------    

        //----------------------------------
        //  urlStream events
        //----------------------------------

        protected function urlStream_openHandler(event:Event):void
        {
            waitingForDataToWrite = false;
            dispatchEvent(event.clone());
        }

        protected function urlStream_progressHandler(event:ProgressEvent):void
        {


            trace("MEMORY:", System.totalMemoryNumber / 1024 / 1024, "MEMORY P:", System.privateMemory / 1024 / 1024, "FREE MEMORY:", System.freeMemory / 1024 / 1024, "PROGRESS:", event.bytesLoaded / event.bytesTotal );




            if(waitingForDataToWrite){
                writeToDisk();
            }       
        }

        protected function urlStream_completeHandler(event:Event):void
        {
            if(urlStream.bytesAvailable > 0)
            {
                writeToDisk();
            }
            //fileStream.close();

            destory();

            dispatchEvent(event.clone());

            // dispatch additional DownloadEvent
            dispatchEvent(new StreamDownloadEvent(StreamDownloadEvent.DOWNLOAD_COMPLETE, urlRequest, file));        
        }

        protected function urlStream_securityErrorHandler(event:SecurityErrorEvent):void
        {
            dispatchEvent(new StreamDownloadEvent(StreamDownloadEvent.ERROR, urlRequest, file, event.errorID.toString()));
            destory();
        }

        protected function urlStream_ioErrorHandler(event:IOErrorEvent):void
        {
            dispatchEvent(new StreamDownloadEvent(StreamDownloadEvent.ERROR, urlRequest, file, event.errorID.toString()));
            destory();
        }   


        //----------------------------------
        //  fileStream events
        //----------------------------------

        protected function fileStream_outputProgressHandler(event:OutputProgressEvent):void
        {
            waitingForDataToWrite = true;
        }   

        protected function fileStream_ioErrorHandler(event:IOErrorEvent):void
        {
            dispatchEvent(new StreamDownloadEvent(StreamDownloadEvent.ERROR, urlRequest, file, event.errorID.toString()));
            destory();
        }   


        //--------------------------------------------------------------------------
        //
        //  Utils
        //
        //--------------------------------------------------------------------------

        private function init():void
        {
            urlStream = new URLStream();
            //fileStream = new FileStream();

            urlStream.addEventListener(Event.OPEN, urlStream_openHandler);
            urlStream.addEventListener(ProgressEvent.PROGRESS, urlStream_progressHandler); 
            urlStream.addEventListener(Event.COMPLETE, urlStream_completeHandler);
            urlStream.addEventListener(IOErrorEvent.IO_ERROR, urlStream_ioErrorHandler);
            urlStream.addEventListener(SecurityErrorEvent.SECURITY_ERROR, urlStream_securityErrorHandler);

            //fileStream.addEventListener(OutputProgressEvent.OUTPUT_PROGRESS, fileStream_outputProgressHandler)
            //fileStream.addEventListener(IOErrorEvent.IO_ERROR, fileStream_ioErrorHandler);        
        }

        private function destory():void
        {
            urlStream.removeEventListener(Event.OPEN, urlStream_openHandler);
            urlStream.removeEventListener(ProgressEvent.PROGRESS, urlStream_progressHandler); 
            urlStream.removeEventListener(Event.COMPLETE, urlStream_completeHandler);
            urlStream.removeEventListener(IOErrorEvent.IO_ERROR, urlStream_ioErrorHandler);
            urlStream.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, urlStream_securityErrorHandler);

            //fileStream.removeEventListener(OutputProgressEvent.OUTPUT_PROGRESS, fileStream_outputProgressHandler)
            //fileStream.removeEventListener(IOErrorEvent.IO_ERROR, fileStream_ioErrorHandler); 

            urlStream = null;
            //fileStream = null;
        }

        private function writeToDisk():void {
            /*var fileData:ByteArray = new ByteArray();
            urlStream.readBytes(fileData, 0, urlStream.bytesAvailable);
            fileStream.writeBytes(fileData,0,fileData.length);
            waitingForDataToWrite = false;*/

            var bytes:ByteArray = new ByteArray();
            urlStream.readBytes( bytes );

            var fs:FileStream = new FileStream();
            fs.open( file, FileMode.APPEND );
            fs.writeBytes( bytes );
            fs.close();
        }




    }
    }


正如我在对CSOMAK的评论中所说,我已经使用URLStream分块方法通过AIR为桌面、iOS和Android成功下载了300+MB的文件

伪代码:

var stream:URLStream = new URLStream();
stream.addEventListener( PROGRESS, progressHandler );
stream.addEventListener( COMPLETE, completeHandler );
stream.load( url );

private function progressHandler( e:ProgressEvent ):void {
    this.writeDataToDisk();
}

private function completeHandler( e:Event ):void {
    this.writeDataToDisk();
}

private function writeDataToDisk():void {
    var bytes:ByteArray = new ByteArray();
    this.stream.readBytes( bytes );

    var fs:FileStream = new FileStream();
    fs.open( file, FileMode.APPEND );
    fs.writeBytes( bytes );
    fs.close();
}
基本逻辑在300MB(可能更高)下正常工作(虽然我应该测试一下,现在我想起来了)。写得相当快,所以可能会有一些错误,我确实缺少一些东西,但你明白了

如果这不起作用,我们需要您提供一些信息:

  • 发布任何错误
  • fs.close()
    之后跟踪
    file.size/1024/1024+“MB”
    ,看看它在崩溃之前能走多远
  • 在fs.close()`之后跟踪
    System.memory/1024/1024+“MB”,以便我们可以监控内存使用情况
  • 对于2和3,我们应该只需要崩溃发生之前的最后一个跟踪语句


    或者,您应该知道,应用程序中的500MB文件将无法执行任何操作。Flash由于其大小而无法加载。我之所以能够处理300MB的视频文件,唯一的原因是我们从磁盘流式传输它们,而不是将整件事存储到内存中。

    因为我不允许通信根据Josh的回答,出于某种原因,我添加了我的版本作为一个单独的答案。但这在很大程度上是基于他的建议。 GitHub也提供了该代码,网址为:

    先决条件-URLStream是一个很棒的类,但它有一个小故障,导致内存泄漏/累积,从而阻止大文件正确加载。我在这里共享的类已经过测试,能够将一系列1.5GB的文件下载到iPad Air 2(64GB)中没有问题。我认为较大的文件也可以,因为它实际上克服了RAM存储限制(在故障修复之前,它在200MB左右崩溃)

    这个小故障-在加载字节上复制的原始数据bytearray永远不会被GC处理(如下所述:),因此,解决方法是实现一个使用Josh技术的类,并确保在写入后处理字节

    …以下是代码(注意:这仍然是预生产):

    …我希望这有帮助

    干杯
    -尼克

    如果你有权访问服务器端,你可以创建一个脚本,一次发送500MB的文件块。但是,如果设备没有足够的RAM来使用它,为什么你需要下载文件呢?您好,我和您使用的技术几乎相同,唯一的区别是,我只在最后关闭FileStream。我现在正在运行一些测试,但它不可用可能无法工作。文件可能确实保存在应用程序专用内存中。下面是一些跟踪日志:trace(“内存:”,System.totalMemoryNumber/1024/1024,“内存P:”,System.privatemory/1024/1024);结果:内存:20.8125内存P:286.0546875,这是文件下载时的25%。最终结果是文件下载时应用程序崩溃。以下是跟踪日志:内存:21.75390625内存P:359.15625可用内存:9.15234375进度:1查找代码时,您从不附加
    fileStream\u outputProgressHandler
    到您的urlstream,因此您的
    waitingForDataToWrite
    属性永远不会设置为true,并且在触发
    COMPLETE
    事件之前,您的数据永远不会写入。我一直在努力让它工作这么久!我试图在完全下载的文件上读取字节\写入字节。显然,由于它的巨大尺寸,应用程序正在崩溃内存不足。但是你的读写分块的方法很有魅力!非常感谢启示录!:)我测试了250Mb的文件,它很好地满足了我的需要。请记住,除非是流式传输,否则你将无法将250Mb的文件真正用于任何事情(也就是说,您无法保存一个250MB的字符串并将其全部读取到内存中,但如果您一次只读取10MB,这是完全可以接受的)。这可能会起作用,但内存管理会非常差。请记住,由于AIR 20和iOS 9,您需要一个额外的设置来确保HTTP流量通过-在清单文件中添加一个条目,其中包括:NSAppTransportSecurityNSAllowsArbitraryLoads…]>FYI:上面的代码示例在iPa上有效D2(iOS 8)、iPad3(iOS 9)和iPhone4S(iOS 9)的结果完全一样——1.5GB+的文件加载很好——没有泄漏。在我的例子中,文件是JPEG、PDF和MPEG4-s,下载的文件可以查看,所以逐字节写入似乎工作得很好。
    package us.flashmx.net 
    {
        import flash.events.ErrorEvent;
        import flash.events.Event;
        import flash.events.EventDispatcher;
        import flash.events.HTTPStatusEvent;
        import flash.events.IEventDispatcher;
        import flash.events.IOErrorEvent;
        import flash.events.ProgressEvent;
        import flash.events.SecurityErrorEvent;
        import flash.filesystem.File;
        import flash.filesystem.FileMode;
        import flash.filesystem.FileStream;
        import flash.net.URLRequest;
        import flash.net.URLStream;
        import flash.system.System;
        import flash.utils.ByteArray;
    
        /**
         * ...
         * @author  Nick Shishenkov <n@vc.am>
         */
        public class LargeFileLoader extends EventDispatcher 
        {
            private var _url:String             = "";
            private var _filePath:String        = "";
            private var _fileStream:FileStream  = new FileStream;
            private var _urlStream:URLStream    = new URLStream;
            private var _localFile:File;
            private var _bytesLoaded:Number;
    
            public function LargeFileLoader() 
            {
                super(null);
    
                //
                _urlStream.addEventListener(Event.OPEN, _onOpen, false, int.MIN_VALUE, true);
                _urlStream.addEventListener(ProgressEvent.PROGRESS, _onProgress, false, int.MIN_VALUE, true);
                _urlStream.addEventListener(Event.COMPLETE, _onComplete, false, int.MIN_VALUE, true);
                _urlStream.addEventListener(IOErrorEvent.IO_ERROR, _onError, false, int.MIN_VALUE, true);
                _urlStream.addEventListener(SecurityErrorEvent.SECURITY_ERROR, _onSecurityError, false, int.MIN_VALUE, true);
                _urlStream.addEventListener(HTTPStatusEvent.HTTP_RESPONSE_STATUS, _onHTTPStatus, false, int.MIN_VALUE, true);
                _urlStream.addEventListener(HTTPStatusEvent.HTTP_STATUS, _onHTTPStatus, false, int.MIN_VALUE, true);
            }
    
            private function _onHTTPStatus(e:HTTPStatusEvent):void 
            {
                dispatchEvent(e.clone());
            }
    
            public function load(remoteURL:String, localPath:String, overwrite:Boolean = true):void
            {
                _url        = remoteURL;
                _filePath   = localPath;
                //
                _localFile      = new File(_filePath);
                _bytesLoaded    = 0;
    
                //
                if (overwrite && _localFile.exists)
                {
                    _localFile.deleteFile();
                }
                //
                _urlStream.load(new URLRequest(url));
                _fileStream.open(_localFile, FileMode.APPEND);
            }
    
            private function _onOpen(e:Event):void 
            {
                dispatchEvent(e.clone());
            }
    
            private function _onSecurityError(e:SecurityErrorEvent):void 
            {
                dispatchEvent(e.clone());
            }
    
            private function _onError(e:IOErrorEvent):void 
            {
                dispatchEvent(new ErrorEvent(ErrorEvent.ERROR, false, false, e.text));
            }
    
            private function _onProgress(e:ProgressEvent):void 
            {
                //
                trace(" -> _onProgress: " + _urlStream.length + " | " + e.bytesLoaded + " / " + e.bytesTotal);
                //
                _writeStreamBytes();
                //
                dispatchEvent(new ProgressEvent(ProgressEvent.PROGRESS, false, false, e.bytesLoaded, e.bytesTotal));
            }
    
            private function _onComplete(e:Event):void 
            {
                _writeStreamBytes();
                //
                dispatchEvent(new Event(Event.COMPLETE));
            }
    
            private function _writeStreamBytes():void
            {
                var bytes:ByteArray = new ByteArray();
                _urlStream.readBytes( bytes );
                _fileStream.writeBytes( bytes );
    
                //
                _bytesLoaded    += bytes.length;
    
                //clear buffer (if the array stays non-null it will lead to a memmory leak
                bytes   = null;
    
            }
    
            public function get url():String 
            {
                return _url;
            }
    
            public function get filePath():String 
            {
                return _filePath;
            }
    
            public function get bytesLoaded():Number 
            {
                //_localFile.size;
                return _bytesLoaded;
            }
    
    
            public function dispose():void
            {
                try{ _fileStream.close(); }catch (err:Error){};
    
                //
                try{ _urlStream.close(); }catch (err:Error){};
    
                //
                _urlStream.removeEventListener(Event.OPEN, _onOpen);
                _urlStream.removeEventListener(ProgressEvent.PROGRESS, _onProgress);
                _urlStream.removeEventListener(Event.COMPLETE, _onComplete);
                _urlStream.removeEventListener(IOErrorEvent.IO_ERROR, _onError);
                _urlStream.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, _onSecurityError);
                _urlStream.removeEventListener(HTTPStatusEvent.HTTP_RESPONSE_STATUS, _onHTTPStatus);
                _urlStream.removeEventListener(HTTPStatusEvent.HTTP_STATUS, _onHTTPStatus);
    
                //
                _urlStream  = null;
                _fileStream = null;
    
                //
                System.gc();
            }
        }
    
    }
    
    package us.flashmx.net 
    {
        import flash.display.DisplayObject;
        import flash.events.Event;
        import flash.events.ProgressEvent;
    
        /**
         * ...
         * @author ...
         */
        public class LargeFileLoader_DEMO extends DisplayObject 
        {
            private var _largeFilesLoader:LargeFileLoader;
    
            public function LargeFileLoader_DEMO() 
            {
                super();
                //
                init_largeFilesLoader("http://A.Large.File.URL/", "/The/Absolute/Local/Path");
            }
    
            public function dispose_largeFilesLoader():void
            {
                //
                if (_largeFilesLoader != null)
                {
                    //clear listeners
                    _largeFilesLoader.removeEventListener(ProgressEvent.PROGRESS, _onFileLoaderProgress);
                    _largeFilesLoader.removeEventListener(Event.COMPLETE, _onFileLoaderComplete);
                    //dispose
                    _largeFilesLoader.dispose();
                    //free mem
                    _largeFilesLoader   = null;
                }           
            }
    
            private function init_largeFilesLoader(fURL:String, fPath:String):void
            {
                //
                _largeFilesLoader   = new LargeFileLoader;
    
                //
                _largeFilesLoader.addEventListener(ProgressEvent.PROGRESS, _onFileLoaderProgress, false, int.MIN_VALUE, true);
                _largeFilesLoader.addEventListener(Event.COMPLETE, _onFileLoaderComplete, false, int.MIN_VALUE, true);
    
                //
                _largeFilesLoader.load(fURL, fPath);
            }
    
            private function _onFileLoaderComplete(e:Event):void 
            {
                trace("All done!");
                dispose_largeFilesLoader();
            }
    
            private function _onFileLoaderProgress(e:ProgressEvent):void 
            {
                _largeFilesLoader.bytesLoaded;
            }
        }
    
    }