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.
[…] Fileupload using AMFPHP, RemoteObject and Flash 10 « Gerton’s Corner (tags: amf php flash flex) […]
Thanks, just what I need!
Even though I would prefer WebORB over the no longer maintained AMFPHP.
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 ;).
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.
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.
@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)
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
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.
@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.
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.
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
Have a look at my response to Andrzej below. Not sure why that works for me but it appears to.
whats the point, if the users dont have flash 10
Hi! Nice script!
Is there a way to trace the upload progress just like the FileReference.upload() method does?
Thank ya
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
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!
[…] 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 […]
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
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..
Its not working with images.
I have the same problem as Matthias.
have you solved this?
thanks
Andrzej
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?
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
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
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.
I find zend a pain to config to work with flex ;(
@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.
Nice and very informative post. Your opinion is more or less the same as main. Thanks!
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.
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
Very good information. Lucky me I came across your site by accident (stumbleupon).
I have book marked it for later!