Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   загрузка нескольких файлов в процентах (http://www.flasher.ru/forum/showthread.php?t=169362)

inozemcev 03.10.2011 18:09

загрузка нескольких файлов в процентах
 
Увидел у 'зеленых носков' их загрузчик и меня заинтересовало следующее : каким образом они определяют в процентах статус загрузки сразу нескольких файлов?
Получается что они получают полную информацию о количестве байт всех файлов еще до того, как они будут загружены. Каким образом они это могли бы реализовать?

Bgg 03.10.2011 18:17

Получают от сервера размеры файлов?

in4core 03.10.2011 18:29

Все довольно просто. Смотри :
1. Узнаем сколько картинок = столько лоадеров. Макс собирает все лоадеры в кучу. Далее есть некая переменная 100 / лоадеры . И так допустим у нас 5 лоадеров - 100 / 5 = 20 . Тоесть каждый лоадер работает в режиме 20% об общего прогресса
2. Овералл = (curloader.bytesLoaded / curloader.bytesTotal)*loaderCounts * 20 ( что то типа того, тока с форумулой помоему напутадл ))

inozemcev 03.10.2011 18:30

Маловероятно. Это обычная as3 библиотека.
Интересно можно ли узнавать количество байт подобным образом.
Код AS3:

var bt:int;
var loader:URLLoader = new URLLoader (new URLRequest ('someResource'));
bt += loader.bitesTotal;
loader =  new URLLoader (new URLRequest ('anotherResource'));
bt += loader.bitesTotal;

И таким образом получить общее кол во байт до загрузки файлов?

in4core 03.10.2011 18:33

Конечно нельзя )) Поток открывается на событии open далее начинается прогресс - где идет получение.
Можно конечно запустить все лоадеры по прогрессу и как только прогресс отработал сразу закрыть поток, но успехов кроме как жуткие задержки перед началом общей загрузки это особых не принесет

inozemcev 03.10.2011 18:39

Цитата:

Сообщение от in4core (Сообщение 1036404)
Все довольно просто. Смотри :
1. Узнаем сколько картинок = столько лоадеров. Макс собирает все лоадеры в кучу. Далее есть некая переменная 100 / лоадеры . И так допустим у нас 5 лоадеров - 100 / 5 = 20 . Тоесть каждый лоадер работает в режиме 20% об общего прогресса
2. Овералл = (curloader.bytesLoaded / curloader.bytesTotal)*loaderCounts * 20 ( что то типа того, тока с форумулой помоему напутадл ))

На сколько я понял количество лоадеров, не обязательно и даже скорее почти всегда не равно количеству загрузок. Конкретно в этом лоадере есть параметр maxConnections который определяет максимальное количество лоадеров для параллельной загрузки.
В принципе можно делить оверол на общее кол-во загрузок и по загрузке каждого конкретного ресурса прибавлять некий процент - долю, но это не совсем точные данные в случае когда мы будем грузить два ресурса один большой другой маленький, визуально будет казаться что 50 процентов загрузилось быстро, а остальные 50 подвисли. Хотелось бы получить точный оверол, выраженный в количестве байт и по событию Event.Progress отнимать bitesLoaded конкретной загрузки, тем самым, обеспечив гибкую и плавную визуализацию процесса загрузки.

Cheburashka 03.10.2011 20:17

Может я что-то не понял. Проблему тоже видимо не так понял.
Есть 3 загрузчика, которые одновременно загружают файлы:
Код AS3:

var arLoaders : Array = [new Loader(), new Loader(), new Loader()]; // утрирую

По энтерфрейму или таймеру опрашиваем их:
Код AS3:

var bytesLoaded : int = 0;
var bytesTotal : int = 0;
for (var i : int = 0; i < arLoaders.lenght; i++) {
    var loader : Loader = Loader(arLoaders[i]);
    bytesLoaded  += loader.contentLoaderInfo.bytesLoaded;
    bytesTotal += loader.contentLoaderInfo.bytesTotal;
}
trace(String((bytesLoaded  / bytesTotal) * 100) + "%");

Или я все-таки не так понял задачу?

in4core 03.10.2011 20:28

так то да, но врядли носки используют кучу лоадеров вместо одного :)

-De- 03.10.2011 20:30

Cheburashka, проблема в том, что пока Loader не начал что-то грузить (не получил первый ответ от сервера), то contentLoaderInfo.bytesTotal у него 0. Например, если вдруг браузер может качать только в один поток, т.е. по очереди эти три лоадера будут грузить, то проценты у тебя три раза добегут до 100)

mikhailk 03.10.2011 20:59

Не надо грузить параллельно.
У пользователей с плохим коннектом будут проблемы.

Я лично поступаю очень просто. Допустим, надо загрузить 5 библиотечных файлов от 400 до 800 кб каждый. Ставим их в очередь и последовательно грузим. При этом всю линейку прогресс-бара делим на количество загружаемых файлов, а внутри каждой сублинейки показываем прогресс загрузки соответствующего файла.

Работает очень симпатично.

stweet 03.10.2011 23:30

Мне кажется зная количество загружаемых файлов не сложно будит построить такую загрузку.
создав общую переменную и к ней прибавлять то что показывает e.bytesLoaded / на количество загружаемых объектов, ну и естественно показывать то что хранится в общей переменной. Так не проще?
Код AS3:

var allPathToFile:Array = ["img1.jpg", "img2.jpg", "img3.jpg"];
var currentObject:int = allPathToFile.lenght;
var allProgress:Number = 0;
var counter:Number = 0;
 
allLoaded (counter);
 
function allLoaded (e:int):void
{
    loader = new loader(allPathToFile[counter])
    // ...
 
    function onLoad(e:Event):void
    {
        // ...
        counter ++;
        allLoaded (counter);
    }
 
    function onProgress(e:ProgressEvent):void
    {
        // по моему в такой ситуации приоритеты выставлять не нужно но я всё же поставил скобки для пущей уверенности.
        allProgress += ((e.bytesTotal / e.bytesLoaded) * 100) / currentObject;
        trace(allProgress + "%");
    }
}


mikhailk 04.10.2011 10:37

e.bytesTotal и e.bytesLoaded - это вроде внутри одного процесса загрузки (одного лоадера)

stweet 04.10.2011 11:43

Ну, если внимательно посмотреть то я использую рекурсивный метод. Т.е. там где стоит "//..." подразумевается часть кода которая и добавляет/удаляет лиснеры и т.п., асам процесс идёт по очерёдно, друг за другом. Если не понятно объяснил не поленюсь накидать полный пример.

Vishapakahr 04.10.2011 12:08

не проверил на практике толька что писал , но теоритически предпологается что будет работать

Код AS3:

package movieclip {
        import flash.display.Loader;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.ProgressEvent;
        import flash.net.URLRequest;
        import flash.text.TextField;
 
        public class MyLoader extends Sprite {
                private var _contentArr:Array;
                private var count:int = 0;
                private var totalBytes:Number = 0;
                private var currentLoaded:Number = 0;
                private var bytesTotalArr:Array = [];
                private var txt:TextField;
 
                public function MyLoader(contentArr:Array) {
                        txt  = new TextField();
                        txt.width = 200;
                        txt.height = 200;
 
                        addChild(txt);
                        this._contentArr = contentArr;
 
                        for (var i:int = 0; i < contentArr.length; i++)
                        {
 
                                var ldr:Loader = new Loader();
                                ldr.name = i.toString();
 
 
                                ldr.load(new URLRequest(contentArr[i]));
                                ldr.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, loading);
                        }
 
 
                        }
 
                        private function loading(e:ProgressEvent):void
                    {
 
 
                                if(e.bytesTotal){
 
                                        e.target.removeEventListener(ProgressEvent.PROGRESS, loading);
                                        totalBytes += e.bytesTotal;
                                        txt.appendText('totalBytes: '+totalBytes+'\n');
                                        bytesTotalArr.push(e.bytesTotal);
                                        count ++;
 
 
                                        if (count == contentArr.length) {
                                                count = 0;
                                                startLoading();
                                                }
                                }
                    }
 
                        private function startLoading():void
                        {
                                var ldr:Loader = new Loader();
                                ldr.name = '0';
                                ldr.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onLoading);
                                ldr.contentLoaderInfo.addEventListener(Event.COMPLETE,done);
                                ldr.load(new URLRequest(contentArr[0]));
                        }
 
                        private function onLoading(e:ProgressEvent):void
                        {
                                txt.appendText('content_'+e.target.name+' loading progress is: '+Math.round((currentLoaded+e.bytesLoaded)/totalBytes)+'\n');
                        }
 
                        private function done(e:Event):void
                        {
                                currentLoaded += bytesTotalArr[Number(e.target.name)];
 
                                count++;
                                txt.appendText('count: '+count+'\n');
 
                                if (count == contentArr.length) {
                                        this.dispatchEvent(new Event('loadingComplete'));
                                        }else{
                                                var ldr:Loader = new Loader();
                                                ldr.name = count.toString();
                                                ldr.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onLoading);
                                                ldr.contentLoaderInfo.addEventListener(Event.COMPLETE,done);
                                                ldr.load(new URLRequest(contentArr[count]));
                                        }
                        }
 
                        public function get contentArr():Array {
                                return _contentArr;
                                }
 
 
                }
 
}


inozemcev 04.10.2011 13:06

Опять же вы привязываетесь к лоадерам. Еще раз говорю, что количество лоадеров и количество загрузок не одно и тоже - загрузок может быть 10, 20, 30 а лоадеров может быть 1, 2, 5 в зависимости от алгоритмов менеджера загрузок. Собственно я и так понимаю, что уперся в невозможность самого actionscript работать с непосредственно файлами. В случае, когда у нас есть сервер и серверный программист наверное будет правильнее получить оверал от сервера, в ином случае придется делать заглушки. Интересно можно ли с помощью HAXE как то обойти ограничения связанные с файловой системой и непосредственно узнать их размер перед загрузкой?

gloomyBrain 04.10.2011 13:53

Как Вы себе это представляете? Может быть Вас это удивит, но HTTP-сервер в любом случае возвращает размер файла (заголовок Content-Length), однако происходит это после открытия соединения (как иначе можно получить размер файла, не спросив об этом сервер?). Файловая система тут вообще не при делах, равно как и HAXE

inozemcev 04.10.2011 14:04

Хорошо, ну а если флеш лежит в том же месте, что и контент. И для оценки размера файлов я не задействую
htttp запрос, есть ли возможность работать с файлами исключительно в той же директории что и флеш?

gloomyBrain 04.10.2011 14:20

Ну, если говорить об AIR - то да, есть свойство size у файлов.

stweet 04.10.2011 14:35

Vishapakahr очень громоздка.
Вот проверенный вариант которым пользуюсь постоянно.
Код AS3:

package  
{
        import flash.display.Bitmap;
        import flash.display.Loader;
 
        import flash.events.Event;
        import flash.events.IOErrorEvent;
        import flash.events.ProgressEvent;
 
        import flash.net.URLRequest;
 
        public class IMGLoader
        {
                private var allPath        :Array = [];
                private var allContent        :Array = [];
 
                private var counter        :int = 0;
 
                private var tmpProgress        :Number = 0;
                private var outProgress        :Number = 0;
 
                private var returnFunction:Function;
                private var progressFunction:Function;
 
                public function IMGLoader(path:Array, re:Function, pro:Function)
                {
                        allPath                = path;
                        returnFunction        = re;
                        progressFunction= pro;
 
                        onLoadFile();
                }
 
                public function onLoadFile ():void
                {
                        var loader:Loader = new Loader();
                            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, COMPLETE);
                            loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, IO_ERROR);
                            loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, PROGRESS);
                            loader.load(new URLRequest(allPath[counter]));
 
 
                        function IO_ERROR(e:IOErrorEvent):void {
 
                                // тут можно подставить что угодно,
                                // либо свою картинку в случае ошибки,
                                // либо оттянуть время и вновь попробовать её загрузить.
                        }
 
                        function COMPLETE(e:Event):void {
 
                                allContent.push(Bitmap(loader.content).bitmapData.clone()); // Копирую содержимое лоадера.
 
                                counter ++;
                                removeAllListener();
                                onLoadFile (); // так как всё идёт благополучно повторяю метод увеличивая счётчик.
 
                                // если все загрузки закончены возвращаем то что нафигачили и можно рубить класс.
                                if (allPath.length == allContent.length) OPERATIONCOMPLETE();
                        }
 
                        // возвращаем процесс загрузки.
                        function PROGRESS(e:ProgressEvent):void {
 
                                tmpProgress = ((e.bytesTotal / e.bytesLoaded) * 100) / allPath.length;
 
                                if (progressFunction != null) progressFunction.call(null, outProgress + tmpProgress);
                        }
 
                        function removeAllListener ():void {
 
                                loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, COMPLETE);
                                loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, IO_ERROR);
                                loader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, PROGRESS);
 
                                loader = null;
 
                                outProgress += tmpProgress / allPath.length;
                        }
 
                        function OPERATIONCOMPLETE():void {
 
                                removeAllListener ();
                                if (returnFunction != null) returnFunction.call(null, allContent);
                        }
                }
        }
}

естественно, после многочисленных проб, просмотреть общую загрузку не удалось и сомневаюсь что удастся.
А если у кого и показан весь процесс, то это только если в xml - ке к пути каждой картинке добавлен её вес, после чего это дело суммируется и вычитается в процессе.

in4core 04.10.2011 14:59

function in function .... ужасть

stweet 04.10.2011 15:04

Цитата:

Сообщение от in4core (Сообщение 1036596)
function in function .... ужасть

согласен, но во многом спасает и экономит, к тому же этот пример написания я довольно часто встречал в книге К.Мука "300 рецептов". Вот как то и приелось. Редко, но метко =)

in4core 04.10.2011 15:10

мук так делает? не знал не знал...


Часовой пояс GMT +4, время: 06:34.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.