Fileupload using AMFPHP, RemoteObject and Flash 10

15 03 2009

File upload with Adobe Flex is a common asked feature for lots of applications. There are several posts on the internet to be found which explain, in detail, how to do this.

Most of these examples however uses the http protocol to transport the binary data. With the arrival of the Adobe Flash 10 player and the new FileReference features that comes with it, it is now also possible to upload a file via a RemoteObject service call.

For the coming example it is assumed that amfphp 1.9 and Flash player 10 (Flex 3.2 SDK) is installed and running. Furthermore i am using a setup as described in one of my earlier posts about RemoteObject and AMFPHP. Download PHPUpload.zip for full example code.

Copy the services contents found in the zip to your amfphp services location (and check the amfphp/globals.php if your “vo” location is configurated to “services/vo/”).

Within your services directory a RemoteFile.php can be found with a public function upload, which require a parameter of type FileVO:


require_once ('./vo/FileVO.php');
class RemoteFile {
/**
* Upload files!
*
* @param FileVO $file
* @return string
**/
public function upload(FileVO $file) {
$data = $file->filedata->data;
file_put_contents( 'uploads/' . $file->filename, $data);
return 'File: ' . $file->filename .' Uploaded ';
}
}

The FileVO php class has a Flex counterpart also called FileVO which is used as a so called RemoteClass. This RemoteClass has an attribute for the filename and filedata (ByteArray).

No we are ready to create the service class for the upload example, this class will be named RemoteFileService and extends the RemoteService super class.public class RemoteFileService extends RemoteService {
private static var phpServiceClass:String = "RemoteFile";
//constructor
public function RemoteFileService(amfChannelId:String, amfChannelEndpoint:String) {
super("remotefileService","amfphp", amfChannelId, amfChannelEndpoint);
}
// Upload function
public function upload(file:FileVO):void {
remoteObject.source = phpServiceClass;
remoteObject.upload.addEventListener(
ResultEvent.RESULT,handleRemoteMethod);
remoteObject.upload(file);
}
// Remote result handler
protected function handleRemoteMethod(event:ResultEvent):void {
var uploadStatus:String;
uploadStatus = event.result.toString();
Application.application.dispatchEvent(
new RemoteResultEvent(RemoteResultEvent.UPLOAD_STATUS, uploadStatus));
}
}

The Flex application file contains a text component (which will be filled with the selected filename), a button for selecting a file and a button to start the upload. Download PHPUpload.zip for full example code.

After a succesfull upload the selected file will be placed in the amfphp/services/uploads directory (needs write privileges!) and an Alert shows a message from the server.


Actions

Information

30 responses

26 03 2009
links for 2009-03-26 « xLight的蓝闪小窝

[…] Fileupload using AMFPHP, RemoteObject and Flash 10 « Gerton’s Corner (tags: amf php flash flex) […]

29 03 2009
Arend

Thanks, just what I need!
Even though I would prefer WebORB over the no longer maintained AMFPHP.

1 04 2009
Matze

When working with remoting to AMFPHP it’s also quite important to watch which Objectencoding you use.
In my experience AMFPHP can have problems registering data-types in complex objects using AMF3 (which AMF0 doesn’t), but if you want to handle ByteArrays however AMF3 seems neccessary.
I lost a good few hours figuring out why the heck my ba’s weren’t being read because of that ;).

2 04 2009
Arend

Just on a side note:
I no longer prefer WebORB. It seems to have a memory leak in handling byteArrays. I now prefer Zend_AMF. Actively maintained by Wade Arnold, former AMFPHP developer.

28 04 2009
Chilli

Thanks for sharing. I’m working on single file upload with Flex3 and AMFPHP
I downloaded your sample and tried, however I got 2 errors

1061: Call to a possibly undefined method load through a reference with static type flash.net:FileReference. PHPUpload.mxml line 57
1119: Access of possibly undefined property data through a reference with static type flash.net:FileReference. PHPUpload.mxml line 65

which are
refUploadFile.load(); //line57
refUploadFile.data.readBytes(data, 0, refUploadFile.data.length); //line65
respectively.

with thousands of thanks.

28 04 2009
Gerton

@Chilli
It seems you are using the wrong Flex SDK. For this to work you need a minimal SDK version of 3.2 (with Flash 10 support)

13 07 2009
Russell Griffith

I had this exact same issue. It is that Flash 10 must be referenced. I found a guide to setting this here:

http://opensource.adobe.com/wiki/display/flexsdk/Targeting+Flash+Player+10

6 05 2009
mojojojo

Hi!

I was considering this approach in my application since everything in it is handled by Zend_Amf_Server on php side and it would be a bit awkward to write special scripts to handle file uploads. But I became really concerned about memory and performance issues.

See, with this approach all the uploaded data is being accumulated in a string variable which means, as I guess, that it’s being stored in RAM. Now, I’m working on a project where video files are to be uploaded. So I guess just a few simultaneous requests can become a disaster.

I’m not really informed on this issue. In fact, looking for answers was the reason I found this page. So I might be pretty wrong. Reading a few thoughts on a subject would be very nice.

6 05 2009
Gerton

@mojojojo
I agree that this method of uploading files will increase your clients memory consumption considerably when using lots of files or very large files.
I think it will be better when you use the FileReference.upload method with some special upload scripts.

7 05 2009
mojojojo

Okay ) It feels good to avoid pitfalls. I guess looking from a performance point sending byte arrays makes sense only when the recipient has to work with them as byte arrays, and even then it’s questionable.

So yes, it’s a pretty solution, but useless from a performance point.

3 06 2009
Matthias

Hi,

I used this example and I have one problem. When I upload a picture, I can see the picture and the name, but the file is empty (0kb).

Problem with byteArray?

grtz

Matthias

18 08 2010
Tobe

Have a look at my response to Andrzej below. Not sure why that works for me but it appears to.

22 06 2009
Nikos

whats the point, if the users dont have flash 10

11 01 2010
Luke

Hi! Nice script!
Is there a way to trace the upload progress just like the FileReference.upload() method does?
Thank ya

11 01 2010
Gerton

Hi Luke,

I am afraid that tracing (i believe that you want some sort of progressbar) is not possible when uploading files via remoting.
The only thing that you might have is a busy cursor indicator.
I personally feel that every requirement needs it’s own solution, so if you need a progressbar or want to upload very large files, use the FileReference.upload() method.
Greetings,
Gerton

11 01 2010
Luke

Thank ya!! My dream was to realize and entire upload manager in remoting including the upload progress event to be traced in a progress bar. Now I perform the upload through the classic FileReference.upload().
Thanks for the quick reply!
Bye!

22 01 2010
Upload any file from Flex with AMFPHP | Rive.be | Blog

[…] I made a succesful AMFPHP multi file upload, by using this as a base. You can read all about it at Gertons’s blog (single file upload) and the Flex{er} blog (his multi file example didn’t work). So in the […]

19 06 2010
Mahedi

Hi,
its working well. i mean, when i kept the RemoteFile.php in service directory its working but when i kept this file in sub directory( service/serviceclass ) its not working.
the following show
unknown runtime problem occurred during a remote call : faultCode:AMFPHP_RUNTIME_ERROR faultString:’Argument 1 passed to RemoteFile::upload() must be an instance of FileVO, array given’ faultDetail:’C:\xampp\htdocs\project\remoteservice\services\serviceclass\RemoteFile.php on line 11′

i’m already show the path in flex also.
private static var phpServiceClass:String = “serviceclass.RemoteFile”;

please guide me to solve the problem.
Thanks,
Mahedi

1 09 2010
Halong

I got it, in gloabls.php, there’s $voPath = “services/vo/”; That’s the file you put your FileVO.php or you can change that to services/serviceclass/vo..

27 07 2010
Andrzej

Its not working with images.
I have the same problem as Matthias.
have you solved this?

thanks
Andrzej

27 07 2010
Gerton

Hi Andrzej,
Just installed the sample again and it is working with any file type, including images on my laptop. Is your upload directory writable? Any messages in your Apache logs\error.log?

28 07 2010
Andrzej

Hi,
I found the problem – it was my fault. I made it working with the drupal 6 file_service and i forgot to encode files as base64..
now it works fine
thank you 🙂
Andrzej

18 08 2010
Tobe

Confused

Same thing as you and Matthias – it creates files with the right name but of 0 bytes.

Standard install of WAMP on an XP x64 machine. Don’t think I’m using any fancy file service.

Where/how/why do I need to encode the data to base64? Or is that not my problem?

Think I’ll resort back to standard file upload in the mean time.

Ta

18 08 2010
Tobe

Hmm – just tried it with

$data = $file->filedata;

instead of

$data = $file->filedata->data;

in the php file and that appears to work.

Still confused.

18 08 2010
Nikos

I find zend a pain to config to work with flex ;(

21 08 2010
Gerton

@Nikos: Well fortunately for you i have posted a blog some time ago about how to setup a zend framework project. This also contains a module called messagebroker which can be used for Flex remoting with Zend_Amf. But you can always use alternatives like AMFPHP or WebORB.

1 12 2010
pozycjonowanie stron

Nice and very informative post. Your opinion is more or less the same as main. Thanks!

31 12 2010
Luis

Hii!!!
I get the error:

unknown runtime problem occurred during a remote call : faultCode:Client.Error.MessageSend faultString:’Send failed’ faultDetail:’Channel.Security.Error error Error #2048: Security sandbox violation

Any ideas??. thanks in advance.

3 01 2011
Gerton

Hi Luis,

Sounds like a standard flex sandbox security error. You can only do remote calls when your flex application is running from the same domain as your used channel endpoint. So if you are running the flex application from flashbuilder, then your endpoint should be localhost (127.0.0.1). There is plenty information on the internet about security, sandbox, crossdomain.xml files etc.

Regards,
Gerton

3 06 2014
váy đầm nữ cá tính cá tính

Very good information. Lucky me I came across your site by accident (stumbleupon).
I have book marked it for later!

Leave a reply to Luke Cancel reply