Envío de imágenes y datos con AS3

En el anterior post, en el apartado El envío de la postal, comentaba que parte del desarrollo consistía en enviar una imagen y distintas variables de Flash al servidor, pero que en AS3 no había una forma sencilla de hacer un envío multipart y habíamos recurrido a la potente librería as3httpclientlib para conseguirlo.

A pesar de que dicha librería funciona perfectamente, lo hace todo mediante sockets, cosa que añade un grado (o varios, según el caso) de dificultad. Como para el proyecto de IKEA no íbamos sobrados de tiempo, no le di más vueltas y la utilicé, pero me quedó la espinita de si no había maneras más sencillas de hacerlo, y desde entonces he estado mirando todo lo relacionado con el tema de envíos desde Flash. Este artículo recoge y explica distintas soluciones que he ido encontrando.

Empezaremos con el caso más sencillo, que es enviar una imagen desde Flash al servidor.

 
Enviar una imagen con AS3

En AS3 contamos con la clase URLRequest, que combinándola con otros métodos para hacer envíos, permite mandar datos como texto, como variables o como binario. Así pues, se puede pasar cualquier archivo como binario, pero para ello primero hay que codificarlo. En el caso de un jpg o un png, podemos utilizar la librería de Adobe as3corelib, que cuenta con las clases JPGEncoder y PNGEncoder, y a partir de un BitmapData (el formato interno de Flash para almacenar datos de una imagen) te genera un ByteArray con la información.

Como ejemplo vamos a crear una imagen a partir de un movieclip que tenemos en el escenario y a enviarla a un php para que la muestre:

Necesitas el Flash Player 9.0.28 para ver esta película

Descargar ejemplo

Nota: para que funcione el ejemplo, tanto el swf como el php se deben encontrar en el mismo dominio.

El código del ejemplo está comentado aunque es bastante sencillito, y la única tarea realmente dura la hace la clase JPGEncoder. Vamos a echar un vistazo a las partes relevantes:

Se toma un "pantallazo" dibujando el movieclip en un bitmapData

AS3:
  1. var bmpData:BitmapData = new BitmapData(foto_mc.width, foto_mc.height);
  2. bmpData.draw(foto_mc);

Se crea un objeto JPGEncoder. El parámetro indica la calidad de la imagen (sobre 100). Se codifica el bitmapData y se asigna a un byteArray.

AS3:
  1. var jpg_codificado:JPGEncoder = new JPGEncoder(99);
  2. var byteArray:ByteArray = jpg_codificado.encode(bmpData);

El tipo de cabecera indica que se trata de un archivo binario

AS3:
  1. var cabecera:URLRequestHeader = new URLRequestHeader("Content-type", "application/octet-stream");

Se crea un objeto URLRequest que contiene toda la información referente al envío. El parámetro data es que el que contiene la foto codificada, y el parámetro vFoto el nombre que le queramos asignar (no es obligatorio).

AS3:
  1. var urlFoto:URLRequest = new URLRequest();
  2. urlFoto.requestHeaders.push(cabecera);
  3. urlFoto.method = URLRequestMethod.POST;
  4. urlFoto.data = byteArray;
  5. urlFoto.url = _ruta + "?vFoto=" + _nombre_foto;

En este ejemplo se manda abrir el php en una ventana en blanco, pero lo normal sería utilizar un objeto URLLoader para enviar la información y procesar el resultado.

AS3:
  1. navigateToURL(urlFoto, "_blank");

Por último, el php se encarga de recibir la imagen y mostrarla por pantalla.

Nota: como son operaciones que mucha gente busca, en el php he incluido una rutina para guardar el archivo en el servidor y otra que da la opción de descargar el fichero al disco duro.

 
Limitaciones de este método

Para cosas muy sencillas el ejemplo anterior es perfecto, pero normalmente, cuando se envía un archivo se suele acompañar también de variables que contienen información. Al asignar a la propiedad data el byteArray, perdemos todas las opciones de adjuntar un objeto con dicha información.

Un "truquillo" sería enviar la foto mediante POST y aprovechar la url para pasar variables por GET, igual que hemos hecho con el nombre del archivo. Por ejemplo:

AS3:
  1. urlFoto.url = "ruta/form.php?vFoto=avatar.jpg&nombre=llops&edad=28";

De todas formas, no es el sistema más limpio, y mejor usarlo como un recurso puntual para pasar pocos parámetros (aunque no tiene nada que ver con el mito de los 256 caracteres).

Lo ideal es poder hacer un envío multipart, igual que se hace con los formularios html o como lo hace la propia clase de AS3 FileReference. Y buscando buscando, di con una clase que sirve perfectamente para el propósito...

 
Enviando una imagen y datos mediante la clase UploadPostHelper

La clase UploadPostHelper te permite pasar un nombre de archivo, un ByteArray y un Object y devuelve otro ByteArray con todo el contenido codificado que podemos enviar como data.

Necesitas el Flash Player 9.0.28 para ver esta película

Descargar ejemplo

El uso sigue siendo muy sencillo: la mayoría de pasos del ejemplo anterior son los mismos, y UploadPostHelper hace todo el trabajo sucio de forma transparente:

AS3:
  1. var urlFicha:URLRequest = new URLRequest();
  2. urlFicha.contentType = 'multipart/form-data; boundary=' + UploadPostHelper.getBoundary();
  3. urlFicha.requestHeaders.push( new URLRequestHeader( 'Cache-Control', 'no-cache' ) );
  4. urlFicha.method = URLRequestMethod.POST;
  5. urlFicha.data = UploadPostHelper.getPostData(_nombre_foto, byteArray, datos);
  6. urlFicha.url = _ruta;

En la segunda linea vemos que se establece el contentType como multipart. El boundary es un string que se genera en cada envío aleatoriamente y sirve para delimitar las diferentes partes del envío. En la cuarta linea es donde se llama al método getPostData, que nos devuelve un array con todos los datos pasados.

Se manda y... ya tenemos nuestro envío multipart. ¿Fácil, no?

 
Mandando varios archivos

Y aunque el método anterior sirve para el 90% de los casos, para rizar el rizo, ya sólo falta poder enviar varios archivos a la vez, cosa que no hace UploadPostHelper, pero sí la librería basada en sockets (as3httpclientlib).

Como no vi nada similar pensé en modificar la clase UploadPostHelper, ya que el trabajo duro estaba hecho, y lo único que falta es permitir añadir nuevas partes, pero para mi sorpresa, mientras me documentaba, he encontrado a alguien que ha escrito una clase con el mismo objetivo hace sólo dos días :)

El post en cuestión es este: http://blog.inspirit.ru/?p=139 y el ejemplo es bastante claro, así que no redundaré para no hacer esto más largo.

 
Resumiendo

A medida que las capacidades de Flash Player crecen, cada vez es más corriente generar imágenes en el mismo player, y también aumenta la necesidad de poder exportarlas. Pero el tema no se reduce sólo a jpgs, sino también a otro tipo de archivos como pdf, zip o mp3.

Gracias a la potencia de AS3 y al esfuerzo de muchas personas que crean todo tipo de librerías y utilidades, llevar a cabo esta tarea se convierte en un paseo, pero detrás hay un trabajo realmente complejo (sólo hay que echar un vistazo a dichas clases).

Con este artículo espero haber allanado un poco el camino por si alguna vez te tienes que enfrentar con el tema.

Post publicado el 18 de January de 2009 a las 22:26 por llops

Categorias: Artículos

Etiquetas: , , , , , , , , , , ,

¿Quieres seguir los comentarios de esta entrada? RSS 2.0

Permalink, Trackback

  • Twitter
  • Meneame
  • Facebook
  • Google Gmail
  • Delicious
  • Share/Bookmark

10 comentarios

  1. #1   Juan

    Este post lo voy a consultar más de una vez... ¿He dicho alguna vez que eres una máquina?? ;D

  2. #2   ErneX

    Excelente post, lo de hacer un POST a un target que sea una URL que contiene variables es realmente útil y creo que es suficiente para los mayoría de los casos en los que sea necesario pasar variables junto con la imagen.

    Pero de igual forma espero que integren en Flash soporte multipart (sin librerías externas ni virguerías mediante sockets) en una futura versión.

  3. Interesante!
    En este post también hablan del tema:
    http://labs.findsubstance.com/2008/04/03/as3-upload-encode-images/

    saludos.

  4. #4   Ditmar

    Me encanto gracias por compartir tus experiencias 100 Puntos ^^

  5. #5   kassel

    Gracias, me sirvio de muxo este post, y el ejemplo, es muy clara la metodologia y la libreria, si os sirve use Matrix para recortar la imagen y PNGencoder para que fuera transparente.
    ;)

  6. #6   Pablo

    He probado este código y funciona bastante bien, pero en Firefox si dices de "guardar imagen como" te lo hace con la extensión form.php, mientras que en IExplorer te lo hace con la extensión form.jpg, Hay alguna manera de solucionar esto?. Gracias.

  7. #7   FCO

    Excelente informacion solo que necesito enviar la imagen al servidor desde un .exe generado por flash sabrias como hacerlo ? Gracias

  8. #8   xleon

    Esas clases del "findsubstance" me han salvado la vida en varias ocasiones. Me refiero al UploadPostHelper.

    Aunque otra buena manera de hacer esto es remoting

  9. #9   Siroko

    AMF to the power!!!

  10. #10   Jose

    Me has salvado la vida!!!! no encontraba forma de mandar imagen y datos!! mil gracias

¡Deja un comentario!

Recuerda:

  • Los programadores son gente noble y sensible (sí, todos), así que pórtate bien y se respetuoso con tus comentarios.
  • Puedes usar las siguientes etiquetas html: <b>, <em> y <a>.
  • Si deseas añadir código utiliza este formato: [as3]code[/as3].
Top