In this article I’ll show the same application I presented at FlexCamp Bucharest Romania 2008 - the video from the conference is available here and although it is in Romanian it might be useful. In the presentation I’m showing the power of Flex: doing complex applications with a few lines of codding.
With this article we are just starting because everything is explained in the powerpoint presentation and by the comments inside the source code found at the end of this article.
The application is simple - only one mxml file - and we will study:
- Multiple Drag and drop (events)
- HTTPService
- FileReference
- URLRequest
On the server-side:
- dir.php - browsing (http service) – no parameters needed – returns a simple XML
- download.php - download (url request) – array with the paths that will be included in archive as parameters – returns an archive (tgz)
- archive.php - class to create arhives
On the client-side:
- Tree ⇒ HTTPService ⇒ dir.php ⇒ HTTPService ⇒ Tree
- Refresh ⇒ HTTPService ⇒ dir.php ⇒ HTTPService ⇒ Tree
- Download ⇒ List ⇒ URLRequest ⇒ FileReference ⇒ file download
We are using multiple selection and dragging so you can drag more that one item from the list. Also the delete key erases the selected items from the list on the right. You can start over by pressing refresh button.
This is the start of it and you can get into it more and more reading the powerpoints and trying the source codes. All this can be downloaded from the end of this article.
Working example is bellow:
What can be added in the future:
- download progress with cancellation possibility
- upload functionality
- user account functionality
The last two points are more difficult because it involves some work on the server-side but is doable.
I’ve posted also the whole flex source code because it is easier to follow the article and study the code in the same page.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 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 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 | <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="439" creationComplete="init()" height="271"> <mx:HTTPService id="dir" url="{SERVER_URL}dir.php" resultFormat="e4x" /> <mx:Tree id="leftTree" x="10" y="10" height="250" width="204" dataProvider="{dir.lastResult}" labelField="@name" showRoot="false" dragEnabled="true" dropEnabled="false" allowMultipleSelection="true" click="showThumb(event)"/> <mx:List id="downloadList" x="222" y="10" height="135" width="207" allowMultipleSelection="true" dataProvider="{fileListProvider}" dragEnter="handleDragEnter(event)" dragOver="handleDragOver(event)" dragDrop="handleDragDrop(event)" dragExit="handleDragExit(event)" click="showThumb(event)" keyUp="handleKeyUp(event)"/> <mx:Button id="downloadButton" x="347" y="153" label="Download" enabled="false" click="initializeDownload(event)" /> <mx:Button id="refreshButton" x="347" y="239" label="Refresh" click="refresh(event)" width="82"/> <mx:Canvas id="imageHolder" x="222" y="153" width="117" height="108"> <mx:Image id="imageThumb" x="0" y="0" width="117" height="108" source="{currentPhotoPath}"/> </mx:Canvas> <mx:Script> <![CDATA[ import mx.messaging.channels.StreamingAMFChannel; /* File downloading application Drag and drop between two different controlers: tree and list */ import mx.rpc.events.ResultEvent; import mx.collections.ArrayCollection; import mx.controls.listClasses.ListBase; import mx.core.UIComponent; import mx.managers.DragManager; import mx.core.DragSource; import mx.controls.List; import mx.events.DragEvent; // internet - on flexer public const SERVER_URL:String = "http://www.flexer.info/wp-content/uploads/2008/05/"; // bindable variable used for the list [Bindable] public var fileListProvider:ArrayCollection = new ArrayCollection(); // bindable variable used for thumbnail [Bindable] public var currentPhotoPath:String = ""; public var fRef:FileReference = new FileReference(); public function init():void { /* initialization function */ // file reference events - used for debug purposes fRef.addEventListener(Event.CANCEL, doEvent); fRef.addEventListener(Event.COMPLETE, doEvent); fRef.addEventListener(Event.OPEN, doEvent); fRef.addEventListener(Event.SELECT, doEvent); fRef.addEventListener(HTTPStatusEvent.HTTP_STATUS, doEvent); fRef.addEventListener(IOErrorEvent.IO_ERROR, doEvent); fRef.addEventListener(ProgressEvent.PROGRESS, doEvent); fRef.addEventListener(SecurityErrorEvent.SECURITY_ERROR, doEvent); // getting folder content dir.send(); } private function handleDragEnter(event:DragEvent):void { /* this function validates the drop */ if (event.dragInitiator is Tree) { var ds:DragSource = event.dragSource; // check if the format is what we need - treeItems if (!ds.hasFormat("treeItems")) return; var items:Array = ds.dataForFormat("treeItems") as Array; for (var i:Number=0; i < items.length; i++) { var item:XML = XML(items[i]); // we want only files to be dragable if (item.@type != "file") return; } // check for the item to be unique var paths:ArrayCollection = downloadList.dataProvider as ArrayCollection; for (var j:Number=0; j < paths.length; j++) { if (item.@path == paths[j].path.toString()) return; } } // accept the drop DragManager.acceptDragDrop(UIComponent(event.currentTarget)); } private function handleDragOver(event:DragEvent):void { /* this function shows feedback to the user */ // show feedback icon DragManager.showFeedback(DragManager.COPY); } private function handleDragDrop(event:DragEvent):void { /* this function adds new items to the list */ // getting source var ds:DragSource = event.dragSource; // getting target var dropTarget:List = List(event.currentTarget); // tempoaray array used to add items to list var arr:Array; // getting the nodes dragged // multiple selection is allowed so we have arrays if (ds.hasFormat("items")) { arr = ds.dataForFormat("items") as Array; } else if (ds.hasFormat("treeItems")) { arr = ds.dataForFormat("treeItems") as Array; } // adding the dragged nodes to list for (var i:Number=0; i < arr.length; i++) { // getting node var node:XML = XML(arr[i]); // creating new list item var item:Object = new Object(); // setting item's properties item.label = node.@name; // we set path also which is needed for download item.path = node.@path; // add to data provider fileListProvider.addItem(item); } // finish drag handleDragExit(event); } private function handleDragExit(event:DragEvent):void { /* this function finishes the drag and drop */ // we hide the feedback var dropTarget:ListBase=ListBase(event.currentTarget); dropTarget.hideDropFeedback(event); // we check the data provider to enable the download button if (dropTarget.dataProvider.length > 0) downloadButton.enabled = true; } private function showThumb(event:MouseEvent):void { /* this function shows the thumbnail used for both tree and list click events */ // if click is on the tree if (event.currentTarget.name == "leftTree") { // folders cannot show thumbnail // other file types than images are automatically not shown if (leftTree.selectedItem.@type == "file") currentPhotoPath = SERVER_URL + leftTree.selectedItem.@path; else currentPhotoPath = ""; // if click is on the list } else if (event.currentTarget.name == "downloadList") { currentPhotoPath = (downloadList.selectedItem ? SERVER_URL + downloadList.selectedItem.path : ""); } } private function handleKeyUp(event:KeyboardEvent):void { /* this function is used for deleting items from the list */ // if we have pressed the DELETE key and // also there is at least one item selected if (event.keyCode == Keyboard.DELETE && downloadList.selectedIndex > -1) { var removeItems:Array = downloadList.selectedIndices; // remove selected items for (var i:Number = 0; i < removeItems.length; i++) { downloadList.dataProvider.removeItemAt(removeItems[i]); } currentPhotoPath = ""; // if the list is empty we disable the download button if (downloadList.dataProvider.length <= 0) downloadButton.enabled = false; } } private function initializeDownload(event:MouseEvent):void { /* this function starts the download we use FileReference to download */ // get the items dragged in the list var paths:ArrayCollection = downloadList.dataProvider as ArrayCollection; // initialize the query/url string var qStr:String = ""; // compose the query/url string // we are sending an array to the server for (var i:int = 0; i < paths.length; i++) qStr += "&name[]="+escape(paths[i].path.toString()); // get the file // the file download.php on the server gets the array // and in the memory creates an tgz archive // and sends it back as being a file (using http headers) // we are using FileReference for this fRef.download( new URLRequest(SERVER_URL + "download.php?" + qStr), "archive.tgz"); } private function doEvent(evt:Event):void { /* Function is displaying events reached when downloading For debug purposes */ var fr:FileReference = evt.currentTarget as FileReference; // for debug purposes */ //trace("type:"+evt.type+", eventString:"+evt.toString()); //trace(fr.creationDate); //trace(fr.creator); //trace(fr.modificationDate); //trace(fr.name); //trace(fr.size); //trace(fr.type); } private function refresh(evt:Event):void { /* Function is refresing both the tree and the list and disables the download button */ // empty the list fileListProvider = new ArrayCollection(); // disable the download button downloadButton.enabled = false; // refresh the tree dir.send(); } ]]> </mx:Script> </mx:Application> |
This is it! As I just wrote at the beginning of the article, the power and beauty of Flex framework is that you can do great things with a few lines of codding. So enjoy Flex!
| ||
| ||
| ||
|
Tags: application, download, drag, drop, FileReference, HTTPService, URLRequest
This post was written by Andrei Ionescu
Views: 10438
























[...] the power of Flex: doing complex applications with a few lines of codding. Read full tutorial and download support files - Possibly related posts: (automatically generated) Tutorial - Desktop RSS with Adobe AIR, Creating HTML AIR Applications [...]
Hi, Great article. I had no problems testing the code. I tried to use my own servers. In the development application (flex) I can run it with no problems but when I call it from the web address I can’t see the file’s list.
You need to use crossdomain.xml file on the server’s root to grant access from outside server’s domain. Please take a look at this cross domain article.
Hi,
how i used the “dataForFormat” when i have a XMLlist using the tag node, and how many format exist.
ex: event.dragSource.dataForFormat(”nodeLabel”).toString();
i from chile.
saludos.
There is a bug. If I download one file and after refreshed I try to download an other the applications do not works.
–
Adobe Flex, Flash Alik View and Business Intelligence
http://www.bintelligence.altervista.org/
Hi, I added some files, clicked refresh, after that could not add new files, they just do not come up in a list.
regards
Hello! Jo and Alex you’re right. There is a bug. Didn’t had time to test it till now. My guess is that there is a problem in the refresh function.
Instead of doing this
do this
Thanks for pointing it out. Also changed in the article. Thank you guys.