En este tip, voy a mostrar como subir imágenes a un servidor utilizando una Aplicación en AIR, desde la aplicación se podrán seleccionar las imágenes que se quieren subir o bien, hacer un Drag&Drop desde el sistema de archivos local. También se muestra una vista previa de la imagen y la opción para borrarla.
Lo primero que debemos de hacer, es crear un proyecto nuevo en Flex y seleccionar el tipo de aplicación que sea de escritorio, o sea, que corra con AIR.
Bien, ya que tenemos nuestro proyecto creado, procederemos a crear la interfaz, lo que mostraremos, serán controles como TileList, Botones y un componente exclusivo para AIR, el FileSystemTree. En el TileList mostraremos las imágenes que se subirán y con los botones controlaremos acciones como: “Eliminar Imágenes” y “Subir Imágenes”. Con el FileSystemTree mostraremos toda la estructura de carpetas y archivos de la computadora que este ejecutando nuestra aplicación y desde ahí se podrán agregar las imágenes también.
Código :
<mx:ApplicationControlBar x="35" y="120" dock="true" height="40">
<mx:Button label="Eliminar Imagenes" icon="{ImageUtil.imagen.Delete}" click="click_eliminar()"/>
<mx:VRule height="100%"/>
<mx:Button label="Subir al Servidor" icon="{ImageUtil.imagen.ServerGo}" click="click_subir()"/>
</mx:ApplicationControlBar>
<mx:HDividedBox width="100%" height="100%">
<mx:FileSystemTree id="archivos_fst" width="250" height="100%" showIcons="true" showExtensions="true"
allowMultipleSelection="true"
allowDragSelection="true" dragEnabled="true" dragMoveEnabled="false"/>
<mx:TileList id="imagenes_tl" width="100%" height="100%" itemRenderer="ir.ImagenIR"
direction="horizontal" allowMultipleSelection="true" dataProvider="{imagenes_ac}"
dragEnter="dragEnter_imagenes(event)" dragDrop="dragDrop_imagenes(event)" dragExit="dragExit_imagenes(event)"/>
</mx:HDividedBox>Crearemos un ItemRenderer que será el que muestre la imagen y su respectivo nombre, este IR consta únicamente de un objeto de tipo Image y un Label.
Código :
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="100" height="130" horizontalAlign="center" verticalAlign="middle"
dataChange="dataChange_this(event)">
<mx:Script>
<![CDATA[
import mx.controls.Label;
import mx.controls.Image;
import mx.events.FlexEvent;
private var imagen:Image;
private var nombre_lbl:Label;
private function dataChange_this(event:FlexEvent):void
{
try
{
//intentamos eliminar el Image y el Label, pues la primera vez no existen
this.removeChild(imagen);
this.removeChild(nombre_lbl);
}
catch (error:Error)
{
}
if (this.data is File)
{
//como cada elemento del ArrayCollection es un File,
//casteamos la variable data
var f:File = File(this.data);
//creamos el objeto que mostrara la imagen
imagen = new Image();
imagen.width = 95;
imagen.height = 95;
//le indicamos a la imagen de donde debe de cargar la imagen
imagen.load(f.url);
//creamos el objeto que mostrara el nombre de la imagen
nombre_lbl = new Label();
nombre_lbl.width = 95;
//asignamos el nombre
nombre_lbl.text = f.name;
//agregamos los objetos al VBox
this.addChild(imagen);
this.addChild(nombre_lbl);
}
}
]]>
</mx:Script>
</mx:VBox>Ya creada la interfaz, procederemos con el código. El código se divide en varias partes, las principales, son para controlar los Drag&Drop desde el FileSystemTree hacia el TileList, para controlar el Drag&Drop desde el sistema de archivos local del sistema hacia nuestra Aplicación, la eliminación de imágenes y para subir las imágenes al servidor.
El Drag&Drop del FileSystemTree al TileList será controlado con los siguiente métodos:
Código :
private function dragEnter_imagenes(event:DragEvent):void
{
//verifico que la fuente sea el FileSystemTree
if (event.dragSource.hasFormat("treeItems"))
{
//le digo que el TileList que muestra las imagenes puede recibir objetos
DragManager.acceptDragDrop(imagenes_tl);
//deshabilito los Listeners de la aplicacion para evitar confusiones de drop
this.removeEventListener(NativeDragEvent.NATIVE_DRAG_DROP, drag_drop_this);
this.removeEventListener(NativeDragEvent.NATIVE_DRAG_ENTER, drag_enter_this);
}
}
private function dragExit_imagenes(event:DragEvent):void
{
//si no suelta los elementos del FileSystemTree en el TileList,
//solamente rehabilitamos los Listeners de la aplicacion
this.addEventListener(NativeDragEvent.NATIVE_DRAG_DROP, drag_drop_this);
this.addEventListener(NativeDragEvent.NATIVE_DRAG_ENTER, drag_enter_this);
}
private function dragDrop_imagenes(event:DragEvent):void
{
//creamos una variable del FileSystemTree que origino el Drag
var fst:FileSystemTree = FileSystemTree(event.dragInitiator);
//vemos cuales son las rutas que fueron seleccionadas
var rutas:Array = fst.selectedPaths;
//agregamos esas rutas a nuestro ArrayColecction de File's
agregaAlDP(rutas);
//rehabilito los Listeners de la aplicacion
this.addEventListener(NativeDragEvent.NATIVE_DRAG_DROP, drag_drop_this);
this.addEventListener(NativeDragEvent.NATIVE_DRAG_ENTER, drag_enter_this);
}El Drag&Drop del sistema de archivos local a nuestra Aplicación será controlado con los siguiente métodos:
Código :
private function dragExit_imagenes(event:DragEvent):void
{
//si no suelta los elementos del FileSystemTree en el TileList,
//solamente rehabilitamos los Listeners de la aplicacion
this.addEventListener(NativeDragEvent.NATIVE_DRAG_DROP, drag_drop_this);
this.addEventListener(NativeDragEvent.NATIVE_DRAG_ENTER, drag_enter_this);
}
private function dragDrop_imagenes(event:DragEvent):void
{
//creamos una variable del FileSystemTree que origino el Drag
var fst:FileSystemTree = FileSystemTree(event.dragInitiator);
//vemos cuales son las rutas que fueron seleccionadas
var rutas:Array = fst.selectedPaths;
//agregamos esas rutas a nuestro ArrayColecction de File's
agregaAlDP(rutas);
//rehabilito los Listeners de la aplicacion
this.addEventListener(NativeDragEvent.NATIVE_DRAG_DROP, drag_drop_this);
this.addEventListener(NativeDragEvent.NATIVE_DRAG_ENTER, drag_enter_this);
}Se generó una función genérica con la cual se alimentará nuestro DataProvider del TileList, se hace una verificación para saber si recibimos un arreglo de File’s o si recibimos un arreglo de Rutas:
Código :
private function agregaAlDP(imgs:Array):void
{
var i:int = 0;
//cuento el numero de elementos del arreglo
var l:int = imgs.length;
//defino la variable que contendra al archivo
var f:File;
for (i = 0; i < l; i++)
{
if (imgs[i] is File)
{
//si el arreglo ya es de File, solo lo casteo
f = File(imgs[i]);
}
else
{
//si el arreglo es de las rutas, instancio la variable
f = new File(imgs[i]);
}
//si lo que se arrastra es un directorio,
//la propiedad extension = null, por eso lo valido
if (f.extension)
{
//lo hago minusculas, por ahi hay muchos .JPG que entrarian a ningun caso
switch (f.extension.toLowerCase())
{
case "png":
case "gif":
case "jpg":
case "jpeg":
{
//solo le permito a los archivos de algun tipo de imagen
imagenes_ac.addItem(f);
break;
}
}
}
}
}Para eliminar las imágenes, únicamente eliminamos los elementos del DataProvider con el siguiente método:
Código :
private function click_eliminar():void
{
//recupero los indices seleccionados y los asigno a un Array
var indices:Array = imagenes_tl.selectedIndices;
var i:int = 0;
//veo cuantos elementos son y le resto 1
var l:int = indices.length - 1;
//recorro el ArrayCollection del fin al principio por que conforme voy eliminando,
//van cambiando los indices
for (i = l; i >= 0; i--)
{
//voy quitando los elementos del ArrayCollection
imagenes_ac.removeItemAt(indices[i]);
}
}Para subir las imágenes de nuestro TileList al server, utilizamos los siguientes métodos:
Código :
private function click_subir():void
{
//inicializo un arreglo nuevo
archivosSeleccionados = [];
var i:int = 0;
//veo cuantos elementos tiene nuestro ArrayColection de File's
var l:int = imagenes_ac.length;
for (i = 0; i < l; i++)
{
//proceso cada elemento por separado
agregarPendiente(File(imagenes_ac.getItemAt(i)));
}
}
private function agregarPendiente(f:File):void
{
//agrego el archivo al arreglo
archivosSeleccionados.push(f);
//agrego Listeners de progreso y de completado
f.addEventListener(ProgressEvent.PROGRESS, progress_f);
f.addEventListener(Event.COMPLETE, complete_f);
//con upload le digo a File que suba el archivo usando el script
//definido en el URLRequest
f.upload(ur);
}
private function progress_f(event:ProgressEvent):void
{
//aquí se puede mostrar el progreso en un ProgressBar, en un TextArea o como más te guste
trace("progressHandler: name=" + File(event.currentTarget).name + " bytesLoaded=" + event.bytesLoaded + " bytesTotal=" + event.bytesTotal);
}
private function complete_f(event:Event):void
{
//cuando se ha subido el archivo, lo quitamos del Array
quitarPendiente(File(event.currentTarget))
}
private function quitarPendiente(f:File):void
{
var i:int = 0;
//vemos cuantos archivos tenemos
var l:int = archivosSeleccionados.length;
for (i = 0; i < l; i++)
{
if (archivosSeleccionados[i].name == f.name)
{
//si el archivo que se subió es el actual del Array, se quita
archivosSeleccionados.splice(i, 1);
if (archivosSeleccionados.length == 0)
{
//si el Array ya no tiene elementos, terminó de subir
terminado();
}
return;
}
}
}
private function terminado():void
{
//Le avisamos al usuario que se han terminado de subir las imagenes
Alert.show("Las imagenes han sido subidas al servidor con éxito!", "Confirmación");
}Y bien ahora va la parte de php, un pequeño script que recibe el archivo y lo mueve a nuestro servidor:
Código :
<?php
$carpeta = "";
$archivo = $carpeta . $_FILES['Filedata']['name'];
if(move_uploaded_file($_FILES['Filedata']['tmp_name'], $archivo))
{
echo "<datos err='no'/>";
}
else
{
echo "<datos err='si'/>";
}
?>Ya solo queda dejar un archivo comprimido con el proyecto de Flex y este script de PHP. El archivo DragAndDrop.zip, incluye dos archivos:
DragDrop.zip que es archivo que se importa desde Flex para que se genere el proyecto.
upload.php que es el script que se encarga de mover las imagenes al servidor.
descargar archivo
¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.

Código :
Pero al momento de querer debuggear la aplicación me sale este error :
Y pues no puedo correr tampoco la aplicación.
Esto lo hice teniendo instalada la nueva versión de AIR y utilizando Flex Builder 3.
Muchas thanks por adela.
Ahora instalé el SDK 4 pero me dá este error
Código :
Mira, de aquí http://opensource.adobe.com/wiki/display/flexsdk/Download+Flex+4, bajate algún Stable Build y pruebas
Por rodrigo morales el 03 de Abril de 2010
Por carlos - peru el 25 de Junio de 2010
los ejemplo en la web solo son php, pero con java no hay