Save/Retrieve ByteArrays to/from Database via AMFPHP

Probably old hat to many folks, but I had to do a bit of googling yesterday to figure this one out and thought I’d write it down lest I forget it all again.

The first gotcha to watch out for (the one that got me, anyway), is making sure that AMFPHP is encoding in AMF3. This can be set in the constructor of the AMFPHP class.

Your AMFPHP class may look like this, for instance:

data')");
		return $result;
	}
	
}
?>

The actionscript is pretty standard AMFPHP/actionscript stuff. The question is: why would you need this? Well, say you have a very complex bit of data containing an indeterminate number of objects in multi dimensional array(s) and you want to save all this as a single object in a single database field. You could manually serialize the mess and write it as one long string – or you could simply write the object to a ByteArray and save it in a ‘blob’ in your database.

Here’s a quick example:

package {

	import flash.display.Sprite;
	import flash.events.Event;
	import flash.net.NetConnection;
	import flash.net.Responder;
	import flash.utils.ByteArray;
	
	/**
	 * send then receive bytearray from database example
	 * @author Devon O. Wolfgang
	 */
	public class Example extends Sprite {
		
		private var resp1:Responder;
		private var resp2:Responder;
		private var nc:NetConnection;
		
		public function Main():void {
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		private function init(e:Event = null):void {
			removeEventListener(Event.ADDED_TO_STAGE, init);
			// entry point
			
			var author1:Object = {	
									firstname : "James", 
									surname : "Ballard"
			}
			
			var author2:Object = {
									firstname : "Hunter",
									surname : "Thompson"
			}
			
			var author3:Object = {	
									firstname : "Chuck", 
									surname : "Palahniuk"
			}
			
			var author4:Object = {
									firstname : "William",
									surname : "Gibson"
			}
			
			var living:Array = [author3, author4];
			var dead:Array = [author1, author2];
			
			var allAuthors:Array = [living, dead];
			
			var ba:ByteArray = new ByteArray();
			ba.writeObject(allAuthors);
			ba.position = 0;
			
			resp1 = new Responder(onGoodSave, onBadReturn);
			resp2 = new Responder(onGoodReturn, onBadReturn);
			nc = new NetConnection();
			nc.connect("http://localhost/amfphp/gateway.php");
			
			// send bytearray to database
			nc.call("ByteSaver.setData", resp1, ba)
		}
		
		// once bytearray has been sent to server
		private function onSave(o:Object):void {
			// if bytearray was inserted into database
			if (String(o) == "true") {
				nc.call("ByteSaver.getData", resp2);
			} else {
				trace ("data not added to database for whatever reason");
			}
		}
		
		// when you retrieve bytearray from server
		private function onGoodReturn(o:Object):void {
			var ba:ByteArray = o as ByteArray;
			ba.position = 0;
			trace (ba.readObject()[0][1].surname); // Gibson
		}
		
		// bad amfphp call
		private function onBadReturn(o:Object):void {
			for (var prop:String in o) trace (prop, o[prop]);
		}
	}
}

Hope that might help someone out. My future self if no one else.


In other news, just saw that my Site GatherAIR thingamabob has now been listed over on Refreshing Apps. Very cool stuff! And thanks to whoever submitted it.

Date: