Passing structured data to flash
I am using the term structured data for arrays, objects, arrays of objects, ...
To put up a specific example, I will consider product details that might be returned from searching a web shop.
The product data will consist of:
- product name
- unit price
- order code
- image (optional)
- related link (optional) - if we are selling radios, this might go to spare batteries
- unit qty / weight (optional)
Note that this scheme is not flexible enough for selling e.g. shoes - you would have
one product name, but perhaps a list of order codes for different sizes
The flash data should be created as an array of objects, like
data = [{prod:'xxx',price:1.11,orderno:123,image:'iii.jpg'},{prod:'abc',price:2.22,orderno:456}];
Method 1 - plain flash vars
Use: loadvariables, Loadvars.load, Loadvars.sendAndLoad
The data string sent from the server could read
prod1=xxx&price1=1.11&orderno1=123&image1=iii.jpg&prod2=abc&price2=2.22&orderno2=456&count=2
Now, if you wanted to build the flash array from the data, you would have to wait for the variables (!)
and then use some code like that
data = [];
for(n = 1 ; n <= Number(count) ; n++)
{ prod = _root['prod'+n];
price = _root['price'+n];
orderno = _root['orderno'+n];
item = {prod:prod, price:price, orderno:orderno};
image = _root['image'+n];
if(typeof(image) != 'undefined')
item.image = image;
related = _root['related'+n];
if(typeof(related) != 'undefined')
item.related = related;
data.push(item);
}
Pro: using urlencode, all characters can be transmitted easily - no special handling required
Pro: data format is easy to understand and verify
Con: all data are received as strings
Con: extending data set to complex structures or multi-dimensional arrays may not be easy - consider data names like xyz13_21
Con: creates lots of variables, so in fact the _root should be replaced by a dedicated MC receiving the vars
Method 2 - comma-separated strings
Use: loadvariables, Loadvars.load, Loadvars.sendAndLoad
The data string sent from the server could read
prods=xxx,1.11,123,iii.jpg,|abc,2.22,456,,
To read that data, you would again wait for data (!) and then use code like this
data = prods.split('|');
for(n = 0 ; n < data.length ; n++)
{ d = data[n].split(',');
item = {prod:d[0], price:d[1], orderno:d[2]};
if(d[3] != '')
item.image = d[3];
if(d[4] != '')
item.related = d[4];
data[n] = item;
}
Pro: small data size
Con: only works when separator chars do not occur within data; this may be hard to achieve, and there is no obvious way to include all characters
Con: all data are received as strings
Con: no easy and fool-proof way to extend the data format - adding a new column to the data in the wrong place may go unnoticed
Con: at least FP5 got severe performance problems splitting those strings
Method 3 - XML
Use: XML.load, XML.sendAndLoad
The data sent from the server might read
<prods>
<item>
<prod>xxx</prod>
<price>1.11</price>
<orderno>123</orderno>
<image>iii.jpg</image>
</item>
<item>
<prod>abc</prod>
<price>2.22</price>
<orderno>456</orderno>
</item>
</prods>
Once the data loads, some actionscript would be necessary to convert the received xml object into the target array
Pro: easy to read and verify; if you care to write a formal specification for the data, you can even use available tools to verify the output of the server script
Pro: easy to extend, data format handles complex structures nicely
Pro: flash client could be replaced by something else
Pro: arrays / objects on the server can more or less automatically be converted into xml and back through inclusion of canned code (distinction between a data item and an array holding exactly 1 item may be lost)
Con: more coding to create and parse the xml than other methods, if it has to be done individually
Con: FP5 did not handle xml parsing too well either
Method 4 - binary
Use: loadmovie
The data is not sent as readable text but rather as a movie consisting of scripts only.
Now, the flash player does not read actionscript source, like the
data = [{prod:'xxx',price:1.11,orderno:123,image:'iii.jpg'},{prod:'abc',price:2.22,orderno:456}];
specification, but only compiled actionscript. So for this method we need something on the server that
compiles actionscript. This could be MING since it includes a full AS compiler.
This could also be a php class or perl package that converts php or perl data into a movie.
Sample MING code
<?
$m = new SWFMovie();
$m->add(new SWFAction("
data = [
{prod:'xxx',price:1.11,orderno:123,image:'iii.jpg'},
{prod:'abc',price:2.22,orderno:456}
];
"));
header('Content-type: application/x-shockwave-flash');
$m->output();
?>
If the data is derived from searching a database, that line of actionscript would have to be created by the
server script first.
The above-mentioned php class works with arrays and provides methods to set a variable or call a function, so code might be
<?
require "swfdata.php";
$data = array(
array(prod=>'xxx', price=>1.11, orderno=>123, image=>'iii.jpg'),
array(prod=>'abc', price=>2.22, orderno=>456)
);
$d = new swfdata();
$d->setvar('prods', $data);
$d->send();
?>
Creating an array from a database search seems to be somewhat easier than creating a string
Pro: no code required in receiving movie, the result data structure just "comes into life" when the transfer completes
Pro: data typing determined by server
Pro: full character set can be passed without any effort
Pro: with appropriate precautions can even pass the foreign server barrier
Con: if any errors occur on the server, a movie transmitting just an error message has to be sent
Con: data is not human readable, so extra software is required to check that a server script is indeed sending correct data
Con: some idiot servers add "banners" to all script output, even to generated swf ... which certainly will not work - and may take ages to diagnose
Sample codes
using constant array create in the programming language
php example
<?
require "swfdata.php";
$m = new swfdata();
$m->setvar('_root.data.counter', array(23, 25));
$m->call('_root.starter', 2.7, array('a', 'b', array('aa'=>11, 'bb'=>'unfug', 'cc'=>0), 'd'));
$m->send();
?>
perl example
#!/usr/bin/perl
require "swfdata.php";
$m = new swfdata();
$m->setvar('_root.data.counter', [23, 25]);
$m->call('_root.starter', 2.7, ['a', 'b', {'aa'=>11, 'bb'=>'unfug', 'cc'=>0}, 'd']);
$m->send();
Method 5 - binary AMF
Use: NetConnection.call etc.
Yet another way of passing binary data, commonly called Flash remoting.
Here the movie can send actionscript objects as a binary message, and the server returns a similar message. Like above, the data on the server would appear as an array or object in the server scripting language.
Sample application - flash part:
var nc = new NetConnection();
nc.connect(url);
var reply = {};
reply.onResult = function(result) {
trace('result is '+result+' ('+typeof(result)+')');
};
nc.call('script1', reply, data1, data2);
Here data1 and data2 are arbitrary flash data items
Sample application - server part:
<?
include "amfdata.php";
$rqst = new amfdata(); // read request data
switch($rqst->fn)
{ case 'script1':
$data = $rqst->fnargs[0];
// process data here
$data = array(-3.7, 4.5);
$rqst->sendresult($data);
}
?>
Pro: passing data in either direction as actionscript objects - all the other methods utilized plain flash vars to send the request.
Pro: data typing determined by server
Pro: full character set can be passed without any effort
Con: if any errors occur on the server, a movie transmitting just an error message has to be sent
Con: undocumented format, typically requires a fairly pricey server solution and uses some not-so-common server languages like CF and hence does not lend itself to experimentation
Con: third-party restriction in effect
Con: data is not human readable, so extra software is required to check that a server script is indeed sending
correct data - for the movie method above one of the available actionscript analyzers should do, there does not seem to be software for amf around.
Con: requires FP6
So far, the latter method was only available together with a suitable server,
now there is a partial php class as well.
Both binary scripts suffer from the fact that PHP does not consider 0xfefefefe as an integer