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:

<?php
class ByteSaver {
 
	function ByteSaver() {
		$GLOBALS['amfphp']['encoding'] = 'amf3';
		mysql_pconnect("SERVER", "NAME", "PASS");
		mysql_select_db("DB");
	}
 
	/**
	 * Grabs byte array from database table named 'bytearray' and sends it back to Flash
	 * @returns ByteArray
	 */
 
	function getData() {
		$result = mysql_query("SELECT * FROM bytearray LIMIT 1");
		$row = mysql_fetch_assoc( $result );
		return new ByteArray($row['byte_array']);
	}
 
	/**
	 * Saves ByteArray from Flash to database table 'bytearray' (in this case the 'byte_array' field is a longblob).
	 * @returns ArrayCollection of all images
	 */
 
	function setData($ba) {
		$result = mysql_query("INSERT INTO bytearray (byte_array) VALUES ('$ba->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.

10 Comments »

  1. Danny Miller says:

    No I found it useful. I have a large project that has been doing this process and also went through the googling phase. I can tell you that this article is one of those that really needs to be indexed on google.

  2. sean says:

    This is brilliant – thank you. It’s very good of you to share this and I owe you a beer!!!

    When you bring in the bytearray object from the server though, i think you can just cast it to bytearray in flash straight away. So towards the end of the as script it ends up something like this:

    private function onGoodReturn(o:ByteArray):void { …

    No need to cast thereafter. Very picky but emphasises the power and ease of access with amfphp.

  3. Devon O. says:

    Very good tip, Sean. Didn’t think to skip that one extra step of casting the return. Very cool!

  4. Dannn says:

    whats the field type for “byte_array”? Is the example done in flex?

    Thx for the post, very interesting.

  5. Dannn says:

    When i pull the byte array in from the database and assign it to a byte array var i get the following:

    cannot convert Object@1ecd80d9 to flash.utils.ByteArray.

    In my amfphp browser the object looks like this:

    (flash.utils::ByteArray)#2
    bytesAvailable = 291
    endian = “bigEndian”
    length = 291
    objectEncoding = 3
    position = 0

    does this look right compared to what you get? Also, have u been going to flash on the beach? if so, i may c u there tomorrow :o

  6. Devon O. says:

    Strange that the browser shows it as a ByteArray, but you can’t type it as one. Been so long since I’ve touched this, I forgot about it (needed it for work the day I blogged this and haven’t touched it since).

    I have been at FOTB. Gonna be at the party at Oceania tonight. I’m the Flash Cowboy.. :)

  7. [...] onebyoneblog Blog Archive Save/Retrieve ByteArrays to/from Database via AMFPHP __________________ http://www.sayphillion.de Mein eigenes kleines Browsergame $suicide->beginTransaction(); $suicide->commit(); [...]

  8. [...] a different path. Or you may want to save the .wav directly in a database as a blob, in which case this old post may help you out. You may also want to name the .wav file on the client side and pass that along as [...]

  9. Sundev says:

    I was getting the dreaded NetConnection.call.badversion occasionally when adding a specific string to my multidimensional array. Specifically, “Lucky Number Slevin” just as a test. It was driving me crazy because it would work all the other times. I finally figured out that I needed to escape the bytearray with mysql_escape_string(). So hopefully this will help others out with intermittent badversion errors.

  10. Sundev says:

    I meant mysql_real_escape_string of course.

RSS feed for comments on this post. / TrackBack URI

Leave a Reply

Devon O. Wolfgang

Technical Reviewer of “The Essential Guide to Flash CS4 AIR Development”

Contributing Author of “Flash AS3 for Interactive Agencies”

Senior Flash Engineer PopCap Games, International Ltd.

Portfolio

Santabot: A Unity3D Flash Game


All right, so a Christmas game like “Santabot vs. The Flying Saucers from Mars” may be a day late[...]

Magnify – a jQuery Plugin


Let me begin by saying right up front, I have not given up on Flash[...]

It’s a Starling Halloween


Getting some practice for the upcoming Zombie Apocalypse[...]

Getting Started with Proscenium

So I had a chance this weekend to sit down and play around with Adobe’s new 3D framework for Stage3D, Proscenium, and thought I’d share a few of the results (a word of caution, there are no preloaders for any of the examples and may load a bit slowly). The first shows some reflections and [...]

Particle Editor for Starling Framework

An in-browser particle editor for the Starling 2D Framework for Flash Player 11.

So Long and Thanks for all the Flash on the Beach

So, another Flash on the Beach has just has just drawn to a close[...]

Game Development Tips from the Trenches of PopCap

Well, this is a post that’s a bit overdue, but, thanks to a well timed bank holiday, I finally had the opportunity to sit down and type up what I’ve been meaning to for some time now…

Old Skool Demoscene FX as 3D Textures

Many moons ago, I got the idea to create some demoscene plane deformation effects in Flash based on the formulas found here: http://www.iquilezles.org/www/articles/deform/deform.htm. I posted my less than desired results up on wonderfl. Thankfully, fellow wonderfl user, Hasufel, forked my attempt and optimized the hell out of it coming up with this. Well, today, for no [...]

Making The Gaming Scene (A Change in Careers)

And for my second blog post of the day, a much more personal note. After about three years of working with, what I would consider as objectively as possible, the best digital agency in Ireland, vStream Digital Media, I have made the immense career decision to leave the agency world and enter the arena of [...]

Feeling Lucky?

Images to dice, kick ascii style [...]

Adventures in Playbook Land

Adventures in Playbook Land


Now that the ordeal is over, I thought I’d take the time to sit down and share my account of what it was like to develop a Blackberry Playbook application using the Adobe Flex SDK[...]

Flash

Draw it for Me

So many ideas – so little time….

Kinect Application Running in Dublin

So, on Friday I just wrapped up our latest project at vStream Digital Media, a Kinect powered flipbook that lets users flip through the hand written notebooks of Philip Lynott of Thin Lizzy. The app uses OpenNI, runs in Adobe AIR and is currently on display at a pretty bitchin’ Phil Lynott exhibition running in [...]

Beach Ball Kinect Party

So we finally got a Kinect camera hooked up to a pc at work and, while it doesn’t seem to be legal to use it for commercial projects (but, hey, I’m no lawyer), the boss asked me to get it figured out and come up with some ideas just in case it would be feasible [...]

Facebook and Flash – A Book Review

Now, I should begin by saying I absolutely hate building Facebook applications. And I build a lot of them at work. Every time I get the word from above that we’re doing another FB app, I just groan – both inwardly and out. It’s become a running joke of the office. Why do I dislike [...]

Multitouch Fluid Dynamics with AIR for Android and RTMFP

The other day I was having some fun playing around with Eugene Zatepyakin’s (aka @inspirit) FluidSolverHD (Actionscript port of C++ fluid dynamics library, MSAFluid. Or is MSAFluid, the processing/java port of the C++ library? In any case it’s a very cool fluid dynamics thingamabob – the HD version using Alchemy). After a bit of tinkering, [...]