Deuxième partie de notre tutorial sur la conception d’une application d’upload FTP avec RobotLegs. Nous avons fait le tour des vues et du model, voyons à présent la dernière vue « DragDropView » écoutant le glissé-déposé de fichiers puis les commandes et le service FTP.
Drag’n’Drop sous SwfStudio
La syntaxe swfStudio est assez particulière mais bon il suffit de bien lire la documentation et vous verrez que tous les objets fonctionnent de la même façon. Voici notre vue DragDropView :
<?xml version="1.0" encoding="utf-8"?> <mx:Canvas xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="100%" height="100%" creationComplete="init()"> <fx:Script> <![CDATA[ import controller.ClientEvent; protected function init():void { ssEvents.addEventListener ({listener : this,recurse:"true",event : "App.onDragDrop",callback : 'onDragDrop'}); } public function onDragDrop(ret_obj) { ssDebug.trace("onDragAndDrop") ssDebug.trace(ret_obj.success) var files_dropped:Array=new Array(); if (ret_obj.success) { var files = ret_obj.result.split("\r"); for (var i=0;i<files.length;i++) { var file=files[i]; var tmpExt = file.substr((file.lastIndexOf(".")+1),file.length); var tmpName = file.substr((file.lastIndexOf('\\')+1),file.length); ssDebug.trace(file+" "+tmpName); // test if file type is allowed if (tmpExt == "mp3" || tmpExt == "jpg") { var file_obj:Object={name:tmpName, url:file}; files_dropped.push(file_obj); }else{ dispatchEvent(new ClientEvent(ClientEvent.ON_APPENED ,tmpName+" n'est pas autorisé ")); //debugger("\n"+ tmpName+" n'est pas autorisé "); } } dispatchEvent(new ClientEvent(ClientEvent.ON_FILES_DROPPED ,files_dropped)); }else{ //debugger("ERROR "); } } ]]> </fx:Script> </mx:Canvas>
Ligne 12 : nous écoutons les éveênements « App.onDragDrop » qui correspondent au déposé de fichiers. La liste des fichiers récupérée arrive comme une chaîne. On la split, puis on vérifie que chaque fichier est autorisé. Pour l’exemple je n’autorise que les fichiers jpg et mp3. Si le fichier est autorisé on l’ajoute à la liste sinon on envoi une erreur à StatView à l’aide de ON_APPENED. Une fois la liste complète, on dispatch un évênement .ON_FILES_DROPPED récupérée par le médiateur et traité vers le model :
package view { import controller.ClientEvent; import model.*; import org.robotlegs.mvcs.Mediator; public class DragDropViewMediator extends Mediator { [Inject] public var dragDropView:DragDropView; [Inject] public var listingModel:ListingModel; override public function onRegister():void { eventMap.mapListener(dragDropView, ClientEvent.ON_FILES_DROPPED, onFilesDropped); eventMap.mapListener(dragDropView, ClientEvent.ON_APPENED, onAppened); } public function onFilesDropped(e:ClientEvent) { listingModel.addToList(e.retour); } public function onAppened(e:ClientEvent) { dispatch(new ClientEvent(ClientEvent.ON_APPENED,e.retour)); } } }
On réutilise ici la fonction listingModel.addToList() vu précédement pour ajouter des éléments à notre ArrayCollection. Cette mise à jour est ensuite dispatchée automatique vers la vue ListingView qui l’utilise comme source de dataprovider.
Voyons à présent notre class FTPService :
package service { import controller.ClientEvent; import exoa.server.FTPConnexion; import exoa.server.FTPConnexionEvent; import flash.events.EventDispatcher; import flash.utils.setTimeout; import model.*; import org.robotlegs.mvcs.Actor; public class FTPService extends Actor { public var isUploading:Boolean; private var connexion:FTPConnexion; [Inject] public var listingModel:ListingModel; public function FTPService() { connexion = new FTPConnexion(); connexion.initialize("exoa.fr", "exoa_ftp_demo", "XXXX"); connexion.addEventListener(FTPConnexionEvent.CONNECT_FAILED, onConnexionFailed); connexion.addEventListener(FTPConnexionEvent.CONNECTED, onConnexionSuccess); connexion.addEventListener(FTPConnexionEvent.CONNECTING, onConnexionLoading); connexion.addEventListener(FTPConnexionEvent.TRANSFER_ITEM_STARTING, onTransferItemStart); connexion.addEventListener(FTPConnexionEvent.TRANSFER_ITEM_PROGRESS, onTransferItemProgress); connexion.addEventListener(FTPConnexionEvent.TRANSFER_ITEM_COMPLETED, onTransferItemComplete); connexion.addEventListener(FTPConnexionEvent.TRANSFER_ITEM_FAILED, onTransferItemFail); } public function connect() { connexion.connect(); debugger("Connexion en cours..."); } public function upload() { if(listingModel._listing.length>0){ var obj:Object = listingModel._listing.getItemAt(0); connexion.uploadFile(obj); debugger("Démarrage de l'upload de " + obj.name); }else { debugger("Tous les uploads sont terminés !"); } } /////////////////// // ON CONNEXION /////////////////// private function onConnexionLoading(e:FTPConnexionEvent):void { debugger("Connexion en cours") } private function onConnexionSuccess(e:FTPConnexionEvent):void { debugger("Connexion FTP réussie") connexion.changeDir("/upload"); } private function onConnexionFailed(e:FTPConnexionEvent):void { debugger("La connexion au server FTP a échouée : "+e.retour.description) } /////////////////// // ON TRANSFER ITEM /////////////////// private function onTransferItemStart(e:FTPConnexionEvent):void { //debugger("Début du transfer."); } private function onTransferItemProgress(e:FTPConnexionEvent):void { dispatch(new FTPConnexionEvent(FTPConnexionEvent.TRANSFER_ITEM_PROGRESS,null,e.valeur)); } private function onTransferItemComplete(e:FTPConnexionEvent):void { debugger("Le transfer est terminé !"); listingModel._listing.removeItemAt(0); var num = setTimeout(upload, 400); } private function onTransferItemFail(e:FTPConnexionEvent):void { debugger("Le transfer du fichier a échoué :"+e.retour.description); } private function debugger(message:String) { dispatch(new ClientEvent(ClientEvent.ON_APPENED, message)); } } }
Cette classe fait office de passerelle avec une classe de connexion FTP, dont la syntaxe est encore bien spécifique à SwfStudio. Vous pouvez remarquer que même les classes de service héritent d’Actor ce qui leur permet d’émettre des évènements vers toute l’application avec dispatch(). Le fonctonnement de cette classe est simple. On injecte le singleton du model de donnée et pour chaque élément se trouvant dans la liste des fichier, on démarre une session d’upload, l’une après l’autre.
Finalement, deux classes dites « commandes » permettent de lancer les fonctionnalités du service. La classe LaunchFTPConnexion :
package controller { import service.FTPService; import org.robotlegs.mvcs.Command; public class LaunchFTPConnexionCommand extends Command { [Inject] public var FTP:FTPService; override public function execute():void { FTP.connect(); } } }
Et la classe LaunchUpload, sensiblement identique :
package controller { import service.FTPService; import org.robotlegs.mvcs.Command; public class LaunchUploadCommand extends Command { [Inject] public var FTP:FTPService; override public function execute():void { FTP.upload(); } } }
Exportez maintenant votre projet swf, et lancez swfStudio. Ouvrez le projet FlexFTPClient.spf se trouvant dans l’archive des sources de ce tutorial, dans le dossier bin-release. Vérifiez que les plugins FTP et filesys sont bien sélectionnés, et cliquez sur BUILD, votre application est créer ! Vous pouvez personnaliser son aspect, ses fonctionnalités.


tit dit:
Bonjour,
Je ne connais pas swfstudio.
Pourquoi l’utilise-t-on?
Merci
Note : Bouton « Commanter » serait à changer en « Commenter »
avr 02, 2010, 15 h 59 minadmin dit:
swfStudio permet simplement de créer des applications exécutables et d’étendre les possibilités de flash. Dans ce cas précis cela me permet d’utiliser le protocole FTP, directement en AS3.
avr 02, 2010, 16 h 32 mintit dit:
Pourquoi n’utilises pas AIR?
avr 02, 2010, 19 h 02 minSur stackoverflow, j’ai trouvé cela: http://stackoverflow.com/questions/63038/as3-ftp-programming-and-the-socket-and-bytearray-classes
admin dit:
effectivement on peut passer par du socket, mais ça reste de la bidouille, il peut y’avoir des problèmes de policy file, d’encodage, et il faut utiliser byteArray pour le transfer des données. Alors que swfStudio, fourni un objet d’accès direct au FTP, le seul désavantages c’est que cela complie un « .exe » qui marche donc uniquement sous windows, mais selon moi, le .air à aussi un désavantage majeur, les gens ne savent en général pas comment on l’ouvre… De plus swfStudio est souvent méconnu des développeurs, donc ce tutorial peut être intéressant
avr 02, 2010, 8 h 35 mintit dit:
ok merci, je regarderai swfstudio sij’ai besoin de créer un exe
avr 02, 2010, 10 h 04 min