Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Flash > ActionScript 3.0

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Ответ
Старый 15.01.2012, 16:22
Sergey_S вне форума Посмотреть профиль Отправить личное сообщение для Sergey_S Найти все сообщения от Sergey_S
  № 1  
Ответить с цитированием
Sergey_S

Регистрация: Jan 2012
Сообщений: 5
По умолчанию При загрузке файлов перепутываются имена файлов

Здравствуйте.
Flash я начал изучать буквально меньше недели назад, поэтому прошу не пинать если что не так). Решил написать мультизагрузчик изображений на сервер с ресайзом на стороне клиента.

Путём проб, ошибок, чтения мануалов и просмотра чужого кода написал код и всё вроде бы работает (фотографии ресайзятся и загружаются), но при загрузке большого количества файлов на сервер, у них(файлов) путаются названия.

К примеру, выбираем файлы: 1.jpg, 2.jpg, 3.jpg, 4.jpg, 5.jpg и загружаем их. На сервере изображение 5.jpg становится 4.jpg, а 1.jpg становится 2.jpg. Возникает ощущение, что эти перепутывания случайны, никакой закономерности не получается обнаружить.

Если загружать 2-3 фотографии, то "перепутываний" названий не происходит.

Сейчас попытаюсь объяснить сам код. По клику по кнопке вызывается метод browse() объекта FileReferenceList. Когда пользователь выбирает файлы, вызывается функция onSelect, в которой запускается цикл с количеством итераций, равным количеству файлов. На каждой итерации создаётся объект FileReference и у него вызывается метод load(), а также в массив ArrayCollection (предназначенный для хранения имён файлов) добавляется элемент с именем файла. На каждой итерации также создаётся addEventListener, который "слушает" загрузку файла во флэш и запускает функцию onLoad(), в которой вызывается метод loadBytes объекта Loader. Далее запускается функция resize() с параметрами BitmapData, размером и именем файла. Элемент с индексом 0 массива ArrayCollection удаляется. Функция resize(), помимо самого ресайза, выполняет и загрузку файлов на сервер.

Вот и сам код:
Код AS3:
        import mx.collections.ArrayCollection;
        import flash.net.URLLoader;
        import flash.net.URLRequest;
        import mx.graphics.codec.JPEGEncoder;
 
        private var fr:FileReferenceList = new FileReferenceList;
        private var reg:RegExp;
        private var fileNames:ArrayCollection = new ArrayCollection; //массив с названиями файлов. Каждый раз из него берётся элемент с индексом 0, затем этот элемент удаляется и так далее
 
        private function onClick():void {
                fr.browse();
                fr.addEventListener(Event.SELECT, onSelect);
         }
 
         private function onSelect(e:Event):void {
                fr.removeEventListener(Event.SELECT, onSelect);
                for (var i:uint = 0; i < fr.fileList.length; i++) {
                      reg = /\.\w+/;
		var fileName:String = fr.fileList[i].name.replace(reg,''); //убираем расширение файла
		fileNames.addItem(fileName); // в массив добавляется название файла
            	var elem:Object = new Object;
	            elem = FileReference(fr.fileList[i]);
	            elem.cancel();
	            elem.load();
	            elem.addEventListener(Event.COMPLETE, onLoad);
                }
           }
 
           private function onLoad(e:Event):void {
	      var loader:Loader = new Loader();
	      loader.contentLoaderInfo.addEventListener(Event.COMPLETE, afterLoad);
	      loader.loadBytes(e.target.data);
          }
 
           private function afterLoad(e:Event):void {
                   var bitmap:Bitmap = e.target.content;
     	        var bitmapData:BitmapData = bitmap.bitmapData;
                   var fileName:String = fileNames[0]; //берётся название текущего файла в цикле
	        fileNames.removeItemAt(0);//элемент с индексом 0 удаляется, а на его месте создаётся новый для следующего файла на следующей итерации
	        resize(bitmapData, 200, fileName);
	        resize(bitmapData, 600, fileName);
           }
 
        	private function resize(bmd:BitmapData, size:Number, fileName:String):void {
        		var scale:Number;
                	var matrix:Matrix = new Matrix();
        		if (bmd.height > bmd.width) {
        			scale = size / bmd.height;
        		}
        		else {
        			scale = size / bmd.width;
        		}
        		matrix.scale(scale, scale);
                	var minBmd:BitmapData = new BitmapData(bmd.width * scale, bmd.height * scale, true, 0x000000);
                	minBmd.draw(bmd, matrix, null, null, null, true);
		var bmp:Bitmap = new Bitmap(minBmd, PixelSnapping.NEVER, true);
		var jpg:JPEGEncoder = new JPEGEncoder();
		var myBytes:ByteArray = jpg.encode(bmp.bitmapData);
		var uploader:URLLoader = new URLLoader();
		var type:String;
		if (size == 600) {
			type = "med";
		}
		else {
			type = "min";
		}
		var request:URLRequest = new URLRequest("uploadFile.php?name="+fileName+"&type="+type);
		var header:URLRequestHeader = new URLRequestHeader("Content-type", "application/octet-stream");
		request.requestHeaders.push(header);
		request.method = URLRequestMethod.POST;
		request.data = myBytes;
		uploader.load(request);
        	}
Надеюсь, код понятен.

Возникает впечатление, что цикл переходит на следующую итерацию, не дождавшись, когда выполнятся все функции, запускаемые по elem.addEventListener(Event.COMPLETE, onLoad);, отсюда и путаница в названиях файлов.

В чём может быть проблема? Буду благодарен за любые мысли.

Вместо массива fileNames:ArrayCollection = new ArrayCollection раньше заводил строковую переменную fileName:String, но во всех итерациях цикла эта переменная принимала одно значение.


Последний раз редактировалось Sergey_S; 15.01.2012 в 16:42. Причина: Отредактировал отступы кода
Старый 15.01.2012, 16:40
FlashRus вне форума Посмотреть профиль Отправить личное сообщение для FlashRus Найти все сообщения от FlashRus
  № 2  
Ответить с цитированием
FlashRus
 
Аватар для FlashRus

Регистрация: Nov 2006
Адрес: СПб
Сообщений: 920
Отправить сообщение для FlashRus с помощью ICQ Отправить сообщение для FlashRus с помощью Skype™
По всей видимости у вас не успевает загрузиться предыдущее изображение и вы начинаете грузить следующее.
Воспользуйтесь рекурсией.

Как только происходит комплит, начинайте грузить следующее изображение, если его номер не превышает общего колличества.


В вашем onSelect запускайте загрузку одного изображения. Слушайте COMPLETE. Как только он произойдёт - начинайте грузить следующее изображение, где опять же начинайте слушать COMPLETE.

Цитата:
Возникает впечатление, что цикл переходит на следующую итерацию, не дождавшись, когда выполнятся все функции, запускаемые по elem.addEventListener(Event.COMPLETE, onLoad);, отсюда и путаница в названиях файлов.
А цикл и не должен ждать. Он просто делает то, что вы в нём напишете. Цикл выполняется фактически мгновенно, а загрузка далеко нет.

И ещё по теме с JPEG. Это работает быстрее, чем использованный вами вариант. Спасибо говорить BlooDHounD
__________________
ЛОДКИ


Последний раз редактировалось FlashRus; 15.01.2012 в 16:57.
Старый 15.01.2012, 16:54
Sergey_S вне форума Посмотреть профиль Отправить личное сообщение для Sergey_S Найти все сообщения от Sergey_S
  № 3  
Ответить с цитированием
Sergey_S

Регистрация: Jan 2012
Сообщений: 5
Спасибо большое за ответ! Сейчас попробую реализовать.
upd. Всё, сделал. Также прикрутил кодировщик jpeg blooddy_crypto.swc, действительно, работает заметно быстрее стандартного.


Последний раз редактировалось Sergey_S; 15.01.2012 в 19:35.
Старый 16.01.2012, 00:15
Stitch512 вне форума Посмотреть профиль Отправить личное сообщение для Stitch512 Найти все сообщения от Stitch512
  № 4  
Ответить с цитированием
Stitch512

Регистрация: Nov 2010
Сообщений: 150
А смысл ждать загрузки предыдущего файла чтобы загрузить следующий, как то не по христиански. А если он вообще не загрузится (собака кабеля погрызла), как минимум обработку ошибок добавить надо. А вообще загрузку по хорошему нужно делать параллельно (в этом и смысл слова "мультизагрузчик"). К примеру, Loader вынести в отдельный класс, в котором будет храниться имя файла, тогда по завершению загрузки будет известно какому файлу соответствуют загруженные данные.


Последний раз редактировалось Stitch512; 16.01.2012 в 00:24.
Старый 17.01.2012, 13:15
Sergey_S вне форума Посмотреть профиль Отправить личное сообщение для Sergey_S Найти все сообщения от Sergey_S
  № 5  
Ответить с цитированием
Sergey_S

Регистрация: Jan 2012
Сообщений: 5
Stitch512, у меня стояла цель сделать загрузчик, как ВКонтакте (там же загрузчик последовательно загружает?), чтобы можно было выбрать сразу несколько файлов и последовательно их загрузить. Важна возможность для пользователя редактировать свойства первой и последующих фотографий, пока загружаются остальные. Обработку ошибок само собой добавлю, когда буду запускать проект.

Кстати, ещё вопрос: оправдано ли я поступил, сделав ресайз на стороне клиента для среднего и малого размера? Ведь в этом случае получается, что для одной фотки придётся сделать три аплода (оригинал фото, средняя и миниатюра). Плюс этого решения в том, что серверу не приходится нагружаться для ресайза. Минус - большой трафик.
Можно было бы сделать загрузку сразу оригинала и последующий ресайз уже на сервере, однако это нехило нагружало бы сервер (фотографии будут загружать до 4МБ). В данном случае плюс как раз меньший трафик.

Я так понимаю тот же ВКонтакте использует первый вариант (ресайзит все варианты фото на клиенте и загружает уже готовые на сервер). Я прав?


Последний раз редактировалось Sergey_S; 17.01.2012 в 13:18.
Старый 17.01.2012, 13:31
goodguy вне форума Посмотреть профиль Найти все сообщения от goodguy
  № 6  
Ответить с цитированием
goodguy
Banned
[+1 05.11.11]
[+1 09.08.11]

Регистрация: Jan 2010
Адрес: РФ. Кемеровская область
Сообщений: 3,243
Цитата:
оправдано ли я поступил, сделав ресайз на стороне клиента для среднего и малого размера?
Конечно оправдано.
А если клиент загрузит какую-нибудь вообще огромную пикчу? Так будет и трафик большой и нагрузка сервера. Конечно это все лучше делать на машине пользователя. Так по крайней мере уже будут примерно известны размеры всех трех картинок в сумме. И трафик, в большинстве случаев, как раз будет меньше.

Создать новую тему Ответ Часовой пояс GMT +4, время: 13:31.
Быстрый переход
  « Предыдущая тема | Следующая тема »  
Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


 


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


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