Création d’un Download Manager avec adobe AIR

Posted on août 11 2010 by Andrea D'Agostino

J’ai longtemps cherché sur Internet sans succès  un outil prêt à l’emploi pour télécharger  plusieurs fichiers depuis un serveur.
J’ai enfin décidé de créer moi-même un petit script en utilisant Flash(as3) et Adobe AIR.
Voici le projet terminé:

http://mp3.mondomix.com/downloadmanager.php

Avant de commencer il vous faut d’abord installer l’extension Adobe AIR pour votre Flash:
http://www.adobe.com/products/air/develop/flash/
Une fois installée, vous auriez la possibilité de configurer et créer votre application AIR depuis Flash.

j’ai commencé par créer un nouveau fichier flash (dwnmngr.fla) et j’ai choisi dans les options de publication l’option « AIR 1.5″ (c’est actuellement ma version de AIR).

air dans flah
Il faut ensuite créer un clip qui va composer la liste des fichiers à télécharger.
J’ai appellé ce clip ‘itemfile’ et coché la case « exporter pour action script ».

itemfile
Le clip est composé d’une barre noire qui sert de background et un champs texte dynamique dont le nom de variable est « flabel ».
J’ai créé un clip pour le bouton de lancement du téléchargement des fichiers (exporté en action script sous le nom « BT »).

Pour le développement des classes j’ai d’abord structuré l’architecture des dossiers qui vont contenir touts mes fichiers  .as, ainsi:

- as3/ : dossier racine des classes
- as3/com/ : ici les classes d’interaction avec les données à distance sur le serveur remote (le serveur qui héberge les fichiers à télécharger)
- as3/layout/: ici les classes pour gérer l’affichage de différents clips qui composent le downloadmanager
- as3/fsystem/ : ici les classes pour lire et enregistrer les fichiers downloadés (interaction avec le FileSystem de l’utilisateur)

J’ai ensuite défini dans les proprietés avancées de « actionscript3″ la classe Main du downloadmanager ainsi que le dossier qui contient toutes les autres classes:

parametresavances
Pour cet version de test j’ai créé à la racine de mon projet (là où il y a mon fichier dwnmngr.fla) un dossier « datas/ » qui contient un fichier XML (fileslist.xml) avec la liste des fichiers à downloader.

/datas/fileslist.xml:

<?xml version='1.0' encoding='utf-8'?>

  <fileslist>

  <fileitem>

  <file_label><![CDATA[Image 1]]></file_label>

  <file_path><![CDATA[http://dartea.com/wp-content/uploads/2010/01/1.jpg]]></file_path>

  <file_name><![CDATA[image1.jpg]]></file_name>

  </fileitem>

<fileitem>

  <file_label><![CDATA[Image 2]]></file_label>

  <file_path><![CDATA[http://dartea.com/wp-content/uploads/2009/12/2.jpg]]></file_path>

  <file_name><![CDATA[image2.jpg]]></file_name>

  </fileitem>

<fileitem>

  <file_label><![CDATA[Image 3]]></file_label>

  <file_path><![CDATA[http://dartea.com/wp-content/uploads/2009/12/3.jpg]]></file_path>

  <file_name><![CDATA[image3.jpg]]></file_name>

  </fileitem>

</fileslist>

Pour lire le fichier XML avec la liste des fichiers à télécharger j’ai commencé par créer une classe dans as3/com/ qui s’appelle « XMLFilesList » dans le fichier XMLFilesList.as.
Cette classe et très simple, il parse le fichier XML et crée un objet XML avec l’ensemble des données. Quand le travail de cette classe est terminé elle renvoie l’évènement « FILESLIST_ENDJOB »:

/as3/com/XMLFilesList.as :

package com

  { 

  import flash.display.MovieClip;

  import flash.events.*;

  import flash.net.*;

  public class XMLFilesList extends MovieClip

  {

  public var  FilesListing:XML;

 public function XMLFilesList():void{

  var RequestXML:URLRequest = new URLRequest("datas/fileslist.xml");

  var LoaderXML:URLLoader = new URLLoader();

  LoaderXML.dataFormat=URLLoaderDataFormat.TEXT; 

  LoaderXML.addEventListener(Event.COMPLETE, XMLLoadSuccessful);

  LoaderXML.addEventListener(IOErrorEvent.IO_ERROR, XMLLoadError); 

  LoaderXML.load(RequestXML);

  }

  private function XMLLoadSuccessful(evt:Event):void{

  FilesListing=new XML(evt.target.data); 

  this.dispatchEvent(new Event("FILESLIST_ENDJOB"));

  }

  private function XMLLoadError(evt:Event):void{

  this.dispatchEvent(evt);

  }

  }

  }

Pour afficher la liste des fichiers à télécharger j’ai créé une classe dans as3/layout/ qui s’appelle « FileListPanel » dans le fichier FileListPanel.as.
Cette classe nécessite comme argument dans le constructeur l’objet XML avec les données (créé par la classe « XMLFilesList « ).
Une fois que l’utilisateur clique sur le bouton « download » un évènement « START_DOWNLOAD » est produit.

/as3/layout/FileListPanel.as :

package layout
{

	import flash.display.*;
 	import flash.events.*;

    public class FileListPanel extends MovieClip
    {

		private var Item:MovieClip;
		private var XMLData:XML;
		private var BTDownload:MovieClip;
		public var DownloadQueue:Array;

		public function FileListPanel(_XMLData):void{
				 XMLData=_XMLData;
				 DownloadQueue=new Array();
				 var startpos:Number=0;
				 var cnt=0;
				 for(var i:String in XMLData..fileitem) {

					  Item=new Itemfile();
					  Item.y=startpos;
					  Item.flabel.text=XMLData.fileitem[i].file_label;
					  Item.fname=XMLData.fileitem[i].file_name;
					  Item.fpath=XMLData.fileitem[i].file_path;
					  startpos+=27;
					  addChildAt(Item,int(i));

					  DownloadQueue[cnt]=[XMLData.fileitem[i].file_name,XMLData.fileitem[i].file_path];

					  cnt++;

				}

				BTDownload=new BT();
				BTDownload.x=200;
				BTDownload.y=startpos+50;
				BTDownload.addEventListener(MouseEvent.CLICK,Download);
				addChild(BTDownload);		

		}

		private function Download(evt:MouseEvent){
			this.dispatchEvent(new Event("START_DOWNLOAD"));
		}

	}
}

Pour gérer la liste des fichiers à télécharger, j’ai créé la classe Downloader dans /as3/fsystem/Downloader.as, c’est le cÅ“ur de l’application.

package fsystem

  {

  import flash.display.MovieClip;

  import flash.net.*;

  import flash.events.*;

  public class Downloader extends MovieClip

  {

  private var I:Number;

  private var DownloadList:Array;

  private var FileSystemObj:Object;

  private  var loader:URLLoader

  public function Downloader(DownloadQueue,AIRFsystem){

  I=0;

  DownloadList=DownloadQueue;

  FileSystemObj=AIRFsystem;

  loader= new URLLoader();

  loader.dataFormat = URLLoaderDataFormat.BINARY; 

  configureListeners();

  GetRemoteFile();

  }

  function GetRemoteFile(){

  var request = new URLRequest(DownloadList[I][1]);

  try {

  loader.load(request);

  } catch (error) {

  trace("Unable to load requested document. ["+DownloadList[I][1]+"]");

  }

  }

  function configureListeners() {

  loader.addEventListener(Event.COMPLETE, completeHandler);

  loader.addEventListener(Event.OPEN, openHandler);

  loader.addEventListener(ProgressEvent.PROGRESS, progressHandler);

  loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);

  loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);

  loader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);

  }

  function completeHandler(event) {

  var loader = URLLoader(event.target);

  //trace("Lecture du fichier remote terminé!");

  var abspath=FileSystemObj.DefaultFilesDir+"/"+DownloadList[I][0];

  FileSystemObj.WriteFile(loader.data,abspath); 

  NextDownload();

  }

 function openHandler(event) {

  trace("openHandler: " + event);

  }

 function progressHandler(event) {

  var loader = URLLoader(event.target);

  trace("progressHandler loaded:" + event.bytesLoaded + " total: " + event.bytesTotal);

  }

 function securityErrorHandler(event) {

  trace("securityErrorHandler: " + event);

  }

 function httpStatusHandler(event) {

  trace("httpStatusHandler: " + event);

  }

 function ioErrorHandler(event) {

  trace("ioErrorHandler: " + event);

  }

  function NextDownload(){

  I++;

  if(I<DownloadList.length){

  GetRemoteFile();

  }else{

  this.dispatchEvent(new Event("END_DOWNLOAD"));

  }

  }

 }

  }

Pour la lecture et l’écriture des fichiers j’ai enfin créé une classe dans as3/fsystem/ qui s’appelle « AIRFsystem » dans le fichier AIRFsystem.as.

/as3/fsystem/AIRFsystem.as :

package fsystem
{

   ///AIR Class
   	import flash.net.*;
	import flash.filesystem.*;
	import flash.events.*;

    public class AIRFsystem
    {

     	public var DefaultFilesDir:String;//directory de destination 

		public function AIRFsystem():void{

				// DEFAULT  DIR
				var UserDescktopDir=File.desktopDirectory.resolvePath("MY_FILES");
				DefaultFilesDir=UserDescktopDir.nativePath;

		}

		 public function WriteFile(bytes,abspath:String){
			 	 var MyFile=new File(abspath);
				 var MyFileStream = new FileStream();
					 MyFileStream.open(MyFile, FileMode.WRITE);
					 MyFileStream.writeBytes(bytes, 0, bytes.length);
					 MyFileStream.close();
		 }

	}
}

La dernière étape avant la publication du fichier AIR a été la construction de la classe Main qui appelle les autres objets.
Voici la classe Main.as (elle doit être dans la racine du projet).

package
{
	import flash.display.*;
	import flash.events.*;
	import flash.system.*;

	import com.*;
	import fsystem.*;
	import layout.*;

   public class Main extends MovieClip
   {

	 private var XMLFilesListObj:XMLFilesList;
	 private var FileListPanelObj:FileListPanel;
	 private var DownloaderObj:Downloader;// ecriture des fichiers (settings et mp3)
	 private var AIRFsystemObj:AIRFsystem;

	 	public function Main() {
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.showDefaultContextMenu = false;
			XMLFilesListObj=new XMLFilesList();
			XMLFilesListObj.addEventListener("FILESLIST_ENDJOB",XML_EndJob);

       }

	    private  function XML_EndJob(event:Event){
		  	trace("XML end Job");
			FileListPanelObj=new FileListPanel(XMLFilesListObj.FilesListing);
			addChild(FileListPanelObj);
		    FileListPanelObj.addEventListener("START_DOWNLOAD",Start_Download);
	   }

	   private function Start_Download(event:Event){
	  		trace("start download");
			AIRFsystemObj=new AIRFsystem();
			DownloaderObj=new Downloader(FileListPanelObj.DownloadQueue,AIRFsystemObj);
			DownloaderObj.addEventListener("END_DOWNLOAD",End_Download);
	   }

	   private function End_Download(event:Event){
		   	trace("Done!");
	   }

   }//end class
}//end

Voici les codes source de ce petit download manager:
downloadmanager_demo.zip

Leave a Reply