AMFPHP ByteArray encoding issue
Categories: actionscript, flash, flex
Written By: sebi
Todays lesson about AMFPHP and ByteArrays.
Let me share some experience about sending ByteArrays to AMFPHP, store them in BLOB fields in MySQL, and after send them back to a Flash client.
Last week I start to develop some funny application, which includes to open image files, crop some part of it, store it in some backend, and after retrive those little images back to a Flash client.
I made the editor in Flex, but the client needs to be in Flash.
I started with the upload. It wasn’t a big whoa, I was able to send the image’s ByteArray to the AMF, and write out to a file. I encoded the image as a png on the client side, to reduce bandwith usage.
The next step was to store it in the database. I decided to use a database instead of file based storing solution is because the files are quite small, only a few hundred bytes, and I also have to store some informations about the images, so it was easier for me to save everything in the same place.
The first trick was that I had to base64_encode the ByteArray, or the MySQL query failed. It was on a little trials-and-errors kind, by the way. The type of the fields for the images are BLOB.
After solving this I made a small mockup viewer, to check if I can retrieve my images back. I create a Flex application, and with reversing the steps everything went fine.
$avatar->headImageBytes = new ByteArray( base64_decode( $data->headImageBytes ) );
(The AMFPHP has a helper class, the ByteArray, which helps you to send back ByteArrays to the client.)
As I’m also using class mapping, so I have one value object, which has as many ByteArray properties, as many images I want to store. I defined the required tags,
var $_explicitType = "com.arcad.models.AvatarModel";
in my php class, and
package com.arcad.models { [Bindable] [RemoteClass(alias="com.arcad.models.AvatarModel")] public class AvatarModel { // ..... } }
in the ActionScript.
And everything worked.
Today I continued the work with moving toward from the dummy Flex app to the Flash application.
Here came the second trick. Which is not really a trick, but some missing thinking. Since the Flash IDE’s compiler has a limited support for the Flex metatags, no wonder it didn’t understand the RemoteClass meta, so after a short brainstorming I realized that I have to add the registerClassAlias as well for the Flash to de-serialize the AMF data correctly.
But for my suprise it wasn’t good enough. The Flash still crying:
TypeError: Error #1034: Type Coercion failed: cannot convert Object@e79de71 to flash.utils.ByteArray. TypeError: Error #1034: Type Coercion failed: cannot convert Object@e79dad9 to flash.utils.ByteArray. TypeError: Error #1034: Type Coercion failed: cannot convert Object@e79d9e9 to flash.utils.ByteArray. TypeError: Error #1034: Type Coercion failed: cannot convert Object@e79d7b9 to flash.utils.ByteArray.
Hm. I started to compare the data I receive from the Flex with the data I received from the Flash with Charles:
It looked like that the AMFPHP knows something about the client - which isn’t a big surprise, as the request is quite different for the pure NetConnection and the Flex’s RemoteObject - but the ObjectEncoding should be the same, as I told the Flash to use AMF3 too.
But it wasn’t enough. After some google and with some luck I found Sephiroth’s article, where in the comments he talks about the following.
When calling amfphp from an actionscript only project (not flex) using NetConnection you must force AMFPHP to use the amf3 encoding otherwise you cannot receive a ByteArray class instance.
So with the help of the line below in the amfphp service class’ constructor:
$GLOBALS['amfphp']['encoding'] = 'amf3';
I was able to get back my images in a Flash client too. Good luck you too.

