Remoting et ByteArray avec Flash et AS3
Par Cédric Tabin le mardi 01.04.2008, 00:50 - ActionScript - Lien permanent
Dans un précédent billet, j'avais montré comment faire simplement du remoting entre flash et php en AS3. En préparant ma démo pour l'AUGG, j'ai voulu pousser un peu plus la chose et transférer des ByteArray depuis mon service amfphp vers flash. Et force est de constater que pour l'instant, c'est la galère !
Mais j'ai finalement trouvé une solution (pas vraiment top, mais qui a le mérite de fonctionner) !
Tout d'abord, voici la première version du service qui lit une image et renvoie son contenu :
<? class Sample { public function getSWF($path) { return new ByteArray(file_get_contents($path)); } } ?>
Et suite à cela, le code dans le fichier flash, selon les informations trouvées sur amfphp.org :
registerClassAlias("ByteArray", ByteArray); //class mapping //... function onResult(obj:ByteArray):void { trace(obj); }
A l'exécution, flash affiche l'erreur suivante :
ReferenceError: Error #1056: Cannot create property data on flash.utils.ByteArray.
Visiblement, le class mapping a fait son effet, mais flash essaie de modifier une propriété 'data' qui semble contenir la chaîne binaire. Hors cette propriété n'existe pas dans la classe ByteArray, ce qui fait logiquement crasher l'application.
De tout évidence, le support de ByteArray n'est pas encore fonctionnel dans Flash (contrairement à Flex)... Il suffirait donc de reprendre ladite chaîne binaire et de remonter un ByteArray manuellement avec :
//... function onResult(obj:Object):void { var binaryString:String = obj.data; var bt:ByteArray = new ByteArray(); bt.writeMultyByte(binaryString, "utf-8"); trace(bt); }
Et pour un SWF d'à peu près 50ko, le trace ne me sort que les 5 premiers caractères !!! Le problème devient donc de passer la chaîne binaire complète depuis php à flash. Et on peut faire cela grâce à cette classe (sur le site de dynamicflash.com) qui permet de reconvertir une chaine encodée via la fonction base64_encode de php. Bien évidemment, c'est pas génial car une chaine encodée en base64 prend environ 33% de place supplémentaire
Au final, le code qui fonctionne se résume à ceci :
<? class Sample { public function getSWF($path) { return base64_encode(file_get_contents($path)); } } ?>
Et du coté flash :
import com.dynamicflash.util.*; //... function onResult(param:String):void { var src:ByteArray = Base64.decodeToByteArray(param); var ldr:Loader = new Loader(); ldr.loadBytes(src); addChild(ldr); }
C'est une solution qui ne me plaît vraiment pas, tout simplement car on ne peut pas faire de class mapping et en plus les données à transférées sont alourdies (bien que l'idéal serait d'utiliser la fonction gzcompress et ByteArray.decompress pour alléger cela). J'espère que les développeurs d'amfphp permettront d'éviter cela dans un futur proche
Commentaires
Nice.
Btw, I am also confused. Why can't the Base64.encode produce the same output as the PHP's base64_encode? In other words, to save bandwidth, I'd rather have the client base64 encode then base64encodetobytearray...
I posted on this forum http://forum.sephiroth.it/showthrea... , maybe a response will come.