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 Software Developer in Dublin, Ireland

Portfolio

Bayer Pixel Bender Filter

Bayer Mosaic Filter in Pixel Bender


Now, seeing as how I’ve been trying to learn some Pixel Bender coding lately[...]

Liquitext

Liquid Text Effect


Haven’t been too active around here lately due to a major on going project at work lately as well as the fact that my wife and I are in the slow process of moving homes. Really, the only free time it seems I have these days is during the lunch hour. So, over the past two days, I came up with this fun little toy during lunches[...]

Google’s Text To Speech Engine in Flash

I’m not sure how I managed to miss this, but I just happened to run across a ‘new’ (well, newish), albeit still unofficial, offering of Google today: text-to-speech. You can see what few details there are on this Techcrunch post. Basically, it just boils down to this though – you send your phrase to be [...]

Quick Sound Effects Generator


Need some beeps, boops, or bops, to go with your UI or games [...]

Quick QuickBox2D Tip II – Collision Detection

Custom collision detection/handling in QuickBox2D [...]

None of This Runs Eternal


No Flash/Actionscript stuff here. Just me rambling about the upcoming Current 93 concert [...]

Playing Around with the New UndoManager

Included in the Flex 4.0 SDK and the, just released, Flash Professional CS5 lies a new hidden little gem of a class: flashx.undo.UndoManager (although the Flex 4.0 SDK’s been out for awhile, I have to admit I didn’t even notice this until I installed Flash CS5 and started poking around the documentation looking for new [...]

Making Waves

In a previous post, “Digging into the Microphone in Flash Player 10.1″, reader David Law asked in the comments how it would be possible to save .wav files to the server. I wasn’t sure right offhand, but thought I’d spend my lunch hour yesterday looking into it. Well, after reading this quick tutorial on Adobe [...]

Some Drawing Fun and a Bad Movie You’ll Never See

Earlier today, Dave Gillem posted a link on Facebook to an incredible Processing based drawing application. Thought I’d have a go at reproducing something similar in Flash. Well, I failed miserably, but the results were still interesting enough to check out. You can play around with it below. Just mouse down to draw in the [...]

Animating Bezier Curves


The other day I got the notion in my head that I wanted to draw some bezier curves in an animated fashion. I’m sure this has been done a million times before, but sometimes reinventing the wheel can be a good learning experience [...]

My God, It’s Full of Stars…


Just a quick little thing I got an idea for (i.e. pretty much ripped off) while browsing Processing examples.

Another Year, Another Look

As a few folks may have noticed, the blog is looking a little bit different as of today [...]

The Webcam Warholizer


Just a little bit of quick Friday fun with webcam and bitmapata…

More With the JiglibFlash Terrain

Playing around a bit more with the animated JiglibFlash terrain idea from my last post, I wanted to see how it would work in conjunction with a webcam. So, needless to say, you’ll need a webcam to check out the results below.

Rockin and Rollin with the JiglibFlash Terrain


Finally got the chance to play around with the new JiglibFlash height map terrain, today, and have to say I am very impressed [...]