Flex: Save binary bytearray data from actionscript 3 to drupal with amfphp
I have been looking for a way to upload a file in flex and save the bytearray directly to drupal via amf. This was written on Drupal 5 however it can easily be added to Drupal 6. Just note there is already a file_services module in D6 and not d5. Here's what I have come up with that works great:
In actionscript 3:
// Use file referance to select a file on the users computer and then load it
public function startUpload():void {
_rf = new FileReference();
_rf = listFiles.selectedItem.file;
_rf.addEventListener(Event.COMPLETE, onLoadComplete);
_rf.load();
}
// On load you can grab the binary data / bytearray from the FileReference.data property
// Make sure you compress the data before you send it.
// Then we call the file.save method with the bytearray and the name of the file
public function onLoadComplete(event:Event):void {
var ba:ByteArray = _rf.data;
ba.compress();
file.save(ba,_rf.name);
}
// Once the file is saved we get returned the file name!
public function onFileSave(event:ResultEvent):void {
var filename:String = event.result;
}
In PHP:
/**
* Implementation of hook_service()
*/
function file_service_service() {
return array(
array(
'#method' => 'file.save',
'#callback' => 'file_service_save',
'#access callback' => 'file_service_save_access',
'#args' => array(
array(
'#name' => 'data',
'#type' => 'struct',
'#description' => t('Save bytearray data to a file'),
),
),
'#return' => 'string',
'#help' => t('Returns the filename saved.')
),
);
}
// This is all pulled from the drupal file_save_data() function with one minor change
function file_service_save($bytearray, $dest, $replace = FILE_EXISTS_RENAME) {
$file = tempnam(realpath(file_directory_temp()), 'file');
if (!$fp = fopen($file, 'wb')) {
drupal_set_message(t('The file could not be created.'), 'error');
return 0;
}
// Here is the magic, we just need to add gzuncompress to the bytearray data
$data = gzuncompress($bytearray->data);
fwrite($fp, $data);
fclose($fp);
if (!file_move($file, $dest, $replace)) {
return 0;
}
return $file;
}
function file_service_save_access() {
return TRUE;
}
Hope this is quite useful for you guys. Note that this will allow any binary file to be saved to the server so you should have some safety precautions to filter harmful extensions and rename them.

Should that be another field defined in file_service_service or is it coming from somewhere else?
Sorry for the late reply, hope you figured it out!
As you can see, I don't have the $dest and $fields defined in the service. I "believe" that if they are omitted they are treated as option. I am definitely sending them though from flex.
Looks good!
Do you know how to get a mp3 file from drupal and play it in flash?
This have been bugging me a while.
Keep up the good work!
// Stefan
Assuming you already have a mp3 player built in flash, you can use amfphp (http://www.amfphp.org/) to call drupal services to get the file. So node.load() on a node with a filefield mp3 and return that data to your flash player.
Am having a problem transferring very large byte arrays. Max filesize we need to be able to transfer is around 40MB. Any help on this is appreciated
I am unsure of the answer to this question. My only suggestion is to test it out yourself.
However, although you could see a progress bar during the flex upload, you would not see a progress bar during the transfer from flex to php.
Post new comment