Статьи

Создание многоразового Flash Uploader с ActionScript 3.0 и PHP

В этом уроке я покажу вам, как создать загрузчик Flash для загрузки файлов с компьютера пользователя. Результат будет идеальным для файлов большого размера, так как на нем будет отображаться индикатор выполнения и процент загрузки. Мы даже покажем пользователю количество загруженных байтов в секунду.


Значок папки Майкл Людвиг .

Примечание редактора: боюсь, здесь нет демоверсии — вам придется скачать source.zip и поиграть с загрузкой файлов на свой собственный сервер 🙂

Создайте новый Flash-файл ActionScript 3.0 и установите размеры 500 х 100 пикселей. Мы начнем с создания кнопки выбора. Нарисуйте прямоугольник со скругленными углами, я сделал мой с круглым углом 5px, синим градиентом и серым штрихом 2px.

Нажмите F8, чтобы превратить его в кнопку и дать ему имя экземпляра «выбрать». Назовите кнопку на сцене «select_btn».

Внутри кнопки заполните 3 состояния немного другим градиентом. Создайте еще один слой над первым и добавьте статическое текстовое поле с текстом «ВЫБЕРИТЕ ФАЙЛ». Лучше всего разделять ресурсы, потому что их легче редактировать позже.

Вернитесь на главную сцену, создайте еще одну скругленную рамку белого цвета и серого штриха. Это будет индикатор выполнения. Я сделал мой так:

Снова нажмите F8 и превратите его в видеоклип с названием «прогресс». Внутри видеоролика о прогрессе создайте еще 2 слоя над первым и переместите белую заливку в третью, оставив только обводку на первом слое. Переименуйте первый слой «margin», второй «bar» и третий «mask» , Мы собираемся превратить третий слой в маску.

На слое «bar» создайте синий прямоугольник с теми же размерами, что и у слоя заливки, но будьте осторожны, чтобы сделать его немного больше, чтобы при применении маски у нас не было отверстий. Поместите его в 0,0 и превратите в видеоклип с именем экземпляра «bar». Это будет бар, который покажет прогресс.

Щелкните правой кнопкой мыши третий слой и выберите «Маска» из меню. У вас должно быть что-то вроде этого:

В библиотеке щелкните правой кнопкой мыши на кнопке выбора, которую мы создали ранее, и выберите «Дублировать». Назовите дубликат «Отмена» и в кнопке измените текст текстового поля на «ОТМЕНА». Мы делаем копию кнопки выбора, которая будет кнопкой отмены. Позже мы покажем только один из них на сцене.

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

Мы почти закончили с активами. Создайте другое текстовое поле, на этот раз динамическое текстовое поле и присвойте ему имя экземпляра «label_txt». Это покажет пользователю сообщение об успехе, сообщение об ошибке или процент выполнения. Убедитесь, что текст недоступен для выбора.

Протестируйте файл, чтобы увидеть, как он идет.

У нас есть только одна вещь, которую нужно сделать, прежде чем мы начнем кодировать; установите класс документа на «Uploader».

В той же папке, что и файл Flash, создайте новый файл ActionScript с именем «Uploader.as». Имя важно для класса, который будет найден. Начните кодировать пакет по умолчанию и импортируйте необходимые классы. Я использовал «import Flash.display. *» Для скорости, но как только мы закончим, мы можем включить только необходимые классы, чтобы уменьшить размер файла.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
package {
     
    import Flash.display.*;
    import Flash.events.*;
    import Flash.text.*;
     
    import Flash.net.FileReference;
    import Flash.net.FileReferenceList;
    import Flash.net.FileFilter;
    import Flash.net.URLRequest;
    import Flash.utils.Timer;
    import Flash.events.TimerEvent;
     
     
    public class Uploader extends MovieClip {
         
    }
}

Мы начнем с установки нескольких переменных:

01
02
03
04
05
06
07
08
09
10
11
12
13
public class Uploader extends MovieClip {
         
        var file:FileReference;
        var filefilters:Array;
        var req:URLRequest;
        var tm:Timer;
        var speed:Number = 0;
        var currbytes:Number = 0;
        var lastbytes:Number = 0;
         
         
         
    }

Создайте функцию конструктора и добавьте следующее:

01
02
03
04
05
06
07
08
09
10
public function Uploader(){
       req = new URLRequest();
       req.url = ( stage.loaderInfo.parameters.f )?
       file = new FileReference();
       setup( file );
       select_btn.addEventListener( MouseEvent.CLICK, browse );
       progress_mc.bar.scaleX = 0;
       cancel_btn.addEventListener( MouseEvent.CLICK, cancelUpload );
       cancel_btn.visible = false;
   }

Позвольте мне объяснить, что здесь происходит:

Мы создаем новый класс URLRequest и устанавливаем URL для загрузки php-файла.

Строка «(stage.loaderInfo.parameters.f)? Stage.loaderInfo.parameters.f: ‘http://www.google.com'» является условной, что означает, что если мы предоставим фильму параметр f , он будет установите URL для параметра f . В противном случае он будет использовать строку, жестко запрограммированную здесь, добрый старый Google, только для тестирования.

Мы выполняем условия, чтобы мы могли повторно использовать файл. Таким образом, мы можем изменить только параметр f с путем к URL, и он будет загружен на указанный URL.

Затем мы создаем новый объект FileReference, класс, обрабатывающий процесс загрузки. Мы передаем объект FileReference в функцию setup (), которую мы позже напишем для настройки различных слушателей.

Наконец, мы добавляем прослушиватели кликов к кнопкам выбора и отмены, устанавливаем масштаб индикатора выполнения в 0 и скрываем кнопку отмены.

Сейчас мы создаем функцию setup ().

1
2
3
4
5
6
7
8
9
private function setup( file:FileReference ){
    file.addEventListener( Event.CANCEL, cancel_func );
    file.addEventListener( Event.COMPLETE, complete_func );
    file.addEventListener( IOErrorEvent.IO_ERROR, io_error );
    file.addEventListener( Event.OPEN, open_func );
    file.addEventListener( ProgressEvent.PROGRESS, progress_func );
    file.addEventListener( Event.SELECT, selectHandler );
    file.addEventListener( DataEvent.UPLOAD_COMPLETE_DATA, show_message );
}

Мы могли бы пропустить события Event.COMPLETE и Event.CANCEL, но я добавил их только для тестирования. Мы настраиваем событие ОТМЕНА, когда пользователь отменяет диалог выбора. У нас есть:

  • событие IO_ERROR, если файл не может быть загружен
  • ОТКРЫТОЕ событие, когда начинается загрузка
  • событие PROGRESS, которое обновит загруженный процент
  • событие SELECT, когда пользователь выбрал файл, и мы автоматически начинаем загрузку
  • и событие UPLOAD_COMPLETE_DATA, которое является настраиваемым событием, запускаемым, когда файл был загружен и файл php ответил на запрос.

Убедитесь, что вы создали все функции событий, иначе вы получите ошибку компиляции.

Мы продолжаем работу с функцией просмотра, которая срабатывает при нажатии кнопки выбора. Мы должны показать диалоговое окно, чтобы пользователь мог выбрать файл:

1
2
3
4
public function browse( e:MouseEvent ){
    filefilters = [ new FileFilter(‘Images’, ‘*.jpg’) ];
    file.browse( filefilters );
}

Обратите внимание, что я добавил объект FileFilter внутри массива и добавил массив в метод обзора FileReference. Вы можете добавить другой тип файла, добавив другой объект FileFilter с другим расширением. Это отфильтрует расширения файлов в диалоговом окне выбора, чтобы пользователь мог выбирать только правильные типы файлов. Это только проверка имени файла, которая не проверяет, является ли файл изображения действительно изображением.

Когда пользователь выбрал файл для загрузки, вызывается событие SELECT. Теперь мы вызываем метод FileReference upload () для загрузки файла в файл php на сервере с аргументом запроса url.

1
2
3
private function selectHandler( e:Event ){
    file.upload( req );
}

Лес создает функцию open_func. Эта функция срабатывает, когда начинается загрузка. Мы скроем кнопку выбора и покажем кнопку отмены.

1
2
3
4
private function open_func( e:Event ){
    cancel_btn.visible = true;
    select_btn.visible = false;
}

Создайте функцию прогресса:

1
2
3
4
5
6
7
private function progress_func( e:ProgressEvent ){
    progress_mc.bar.scaleX = e.bytesLoaded / e.bytesTotal;
    var tf = new TextFormat();
    tf.color = 0x000000;
    label_txt.defaultTextFormat = tf;
    label_txt.text = Math.round( (e.bytesLoaded/e.bytesTotal)*100)+’% uploaded’;
}

Позвольте мне объяснить, что здесь происходит. Мы устанавливаем масштаб полосы видеоклипа, показывающей загруженный процент. Это достигается путем деления bytesLoaded на свойства bytesTotal объекта события. Событие progress предоставляет нам количество загруженных байтов и общее количество байтов файла.

Затем мы создаем объект TextFormat и устанавливаем черный цвет (0x000000) для текстовой метки. Нам понадобится этот шаг, потому что позже мы изменим цвет текста на зеленый или красный в зависимости от сообщения.

Наконец, мы устанавливаем текстовое поле с процентом загрузки.

Мы создадим функцию ошибки:

1
private function io_error( e:IOErrorEvent ){ var tf = new TextFormat();

По сути, мы меняем цвет текста метки, устанавливаем для него сообщение об ошибке, а затем меняем местами кнопки отмены и выбора.

Давайте создадим функцию show_message, которая будет проверять, была ли загрузка успешной:

01
02
03
04
05
06
07
08
09
10
11
12
private function show_message( e:DataEvent ){
    var tf = new TextFormat();
    if( e.data == ‘ok’ ){
        tf.color = 0x009900;
        label_txt.defaultTextFormat = tf;
        label_txt.text = ‘The file has been uploaded.’;
    } else if( e.data == ‘error’){
        tf.color = 0xff0000;
        label_txt.defaultTextFormat = tf;
        label_txt.text = ‘The file could not be uploaded.’;
    }
}

Здесь мы проверяем, является ли свойство data события UPLOAD_COMPLETE_DATA ‘ok’ или ‘error’ и показываем ли сообщение соответствующим образом. Свойство data этого события содержит ответ сервера от сценария php.

Это последняя функция, которая будет срабатывать при нажатии кнопки отмены. Это вызывает функцию cancel () FileReference для отмены загрузки. Мы также вызываем метод reset () для очистки.

1
2
3
4
private function cancelUpload( e:MouseEvent ){
    file.cancel();
    reset();
}

Мы запускаем функцию reset () для очистки ресурсов, устанавливаем текст в «» и меняем кнопки отмены и выбора:

1
2
3
4
5
6
private function reset(){
    cancel_btn.visible = false;
    select_btn.visible = true;
    label_txt.text = »;
    progress_mc.bar.scaleX = 0;
}

Идите дальше и протестируйте файл во Flash.

На данный момент загрузка работает, но в конце мы получаем сообщение об ошибке. Это связано с тем, что мы не указали параметр path, поэтому swf берет жестко закодированную страницу Google. Так как эта страница не возвращает нам «хорошо», мы получаем ошибку. Мы должны построить файл php ..

Давайте покажем пользователю скорость, с которой он загружает. В функцию конструктора добавьте строки:

1
2
tm = new Timer( 1000 );
tm.addEventListener( TimerEvent.TIMER, updateSpeed );

Мы создаем таймер, который будет работать каждую секунду и будет проверять скорость.

В функцию open_func () добавьте эту строку:

1
tm.start();

Это запустит таймер, когда начнется загрузка. Теперь мы создадим метод updateSpeed ​​():

1
2
3
4
private function updateSpeed( e:TimerEvent ){
    speed = Math.floor( (currbytes — lastbytes)/1024 );
    lastbytes = currbytes;
}

Вот что здесь происходит: мы вычисляем скорость, вычитая переменные lastbytes из currbytes . Переменная lastbytes впоследствии устанавливается в currbytes . Таким образом, когда обе переменные равны 0, скорость равна 0. Переменная currbytes будет содержать текущее количество загруженных байтов. Мы не можем получить к нему доступ напрямую, поэтому мы создали переменную currbytes. Эта переменная будет установлена ​​из нашего события PROGRESS, где мы можем получить доступ к свойству bytesLoaded.

Наконец, мы делим все на 1024, чтобы получить результат в килобайтах, и округляем значение для отображения с помощью Math.floor ().

Давайте добавим последнюю модификацию, чтобы мы могли перейти к сценарию php. В progress_func () измените строку:

1
label_txt.text = Math.round( (e.bytesLoaded/e.bytesTotal)*100)+’% uploaded’;

с этим:

1
label_txt.text = Math.round( (e.bytesLoaded/e.bytesTotal)*100)+’% uploaded ‘+speed+’ kb/s’;

Вот полный код загрузчика Flash:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package {
     
    import Flash.display.*;
    import Flash.events.*;
    import Flash.text.*;
     
    import Flash.net.FileReference;
    import Flash.net.FileReferenceList;
    import Flash.net.FileFilter;
    import Flash.net.URLRequest;
    import Flash.utils.Timer;
    import Flash.events.TimerEvent;
     
     
    public class Uploader extends MovieClip {
         
        var file:FileReference;
        var filefilters:Array;
        var req:URLRequest;
        var tm:Timer;
        var speed:Number = 0;
        var currbytes:Number = 0;
        var lastbytes:Number = 0;
         
        public function Uploader(){
            req = new URLRequest();
            req.url = ( stage.loaderInfo.parameters.f )?
            file = new FileReference();
            setup( file );
            select_btn.addEventListener( MouseEvent.CLICK, browse );
            progress_mc.bar.scaleX = 0;
            tm = new Timer( 1000 );
            tm.addEventListener( TimerEvent.TIMER, updateSpeed );
            cancel_btn.addEventListener( MouseEvent.CLICK, cancelUpload );
            cancel_btn.visible = false;
        }
         
        public function browse( e:MouseEvent ){
            filefilters = [ new FileFilter(‘Images’, ‘*.jpg’) ];
            file.browse( filefilters );
        }
         
        private function setup( file:FileReference ){
            file.addEventListener( Event.CANCEL, cancel_func );
            file.addEventListener( Event.COMPLETE, complete_func );
            file.addEventListener( IOErrorEvent.IO_ERROR, io_error );
            file.addEventListener( Event.OPEN, open_func );
            file.addEventListener( ProgressEvent.PROGRESS, progress_func );
            file.addEventListener( Event.SELECT, selectHandler );
            file.addEventListener( DataEvent.UPLOAD_COMPLETE_DATA, show_message );
        }
         
        private function cancel_func( e:Event ){
            trace( ‘canceled !’ );
        }
         
        private function complete_func( e:Event ){
            trace( ‘complete !’ );
        }
         
        private function io_error( e:IOErrorEvent ){
            var tf = new TextFormat();
            tf.color = 0xff0000;
            label_txt.defaultTextFormat = tf;
            label_txt.text = ‘The file could not be uploaded.’;
            tm.stop();
            cancel_btn.visible = false;
            select_btn.visible = true;
        }
         
        private function open_func( e:Event ){
            //trace( ‘opened !’ );
            tm.start();
            cancel_btn.visible = true;
            select_btn.visible = false;
        }
         
        private function progress_func( e:ProgressEvent ){
            progress_mc.bar.scaleX = e.bytesLoaded / e.bytesTotal;
            var tf = new TextFormat();
            tf.color = 0x000000;
            label_txt.defaultTextFormat = tf;
            label_txt.text = Math.round( (e.bytesLoaded/e.bytesTotal)*100)+’% uploaded ‘+speed+’ kb/s’;
            currbytes = e.bytesLoaded;
        }
         
        private function selectHandler( e:Event ){
            file.upload( req );
             
        }
         
        private function show_message( e:DataEvent ){
            tm.stop();
            var tf = new TextFormat();
            if( e.data == ‘ok’ ){
                tf.color = 0x009900;
                label_txt.defaultTextFormat = tf;
                label_txt.text = ‘The file has been uploaded.’;
            } else if( e.data == ‘error’){
                tf.color = 0xff0000;
                label_txt.defaultTextFormat = tf;
                label_txt.text = ‘The file could not be uploaded.’;
            }
        }
         
        private function updateSpeed( e:TimerEvent ){
            speed = Math.round( (currbytes — lastbytes)/1024 );
            lastbytes = currbytes;
        }
         
        private function cancelUpload( e:MouseEvent ){
            file.cancel();
            reset();
        }
         
        private function reset(){
            cancel_btn.visible = false;
            select_btn.visible = true;
            label_txt.text = »;
            progress_mc.bar.scaleX = 0;
        }
         
    }
}

Давайте быстро создадим наш php-скрипт:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
<?php
 
$uploads_dir = ‘./uploads/’;
 
if( $_FILES[‘Filedata’][‘error’] == 0 ){
 
  if( move_uploaded_file( $_FILES[‘Filedata’][‘tmp_name’], $uploads_dir.$_FILES[‘Filedata’][‘name’] ) ){
 
  echo ‘ok’;
 
  exit();
 
  }
 
  }
 
  echo ‘error’;
 
  exit();
 
?>

Я просто быстро подведу итоги (PHP не входит в рамки этой статьи). Мы определяем путь, куда мы поместим файл, затем проверяем, равен ли $ _FILES [‘Filedata’] [‘error’] 0 (если ошибок нет). Затем мы проверяем, успешно ли move_uploaded_file () передал файл в папку, и показываем «ok» или «error» в зависимости от результата.

И последнее замечание: вам нужно убедиться, что папка существует и доступна для записи, прежде чем запускать скрипт.

Это конец нашего урока. Спасибо за чтение, я надеюсь, что вы узнали что-то!