Flex and Flash file uploading with return data
The addition of the FileReference class in AS2 made file uploading significantly easier in Actionscript. However, one issue that remained problematic was the ability to get detailed information back from the server once the upload was complete. The best you could do was to get a '200' response saying the file upload had completed, but there was no easy way to return additional data from the server with respect to the uploaded process .... until now.
Adobe has finally added the missing piece to accomplish a nice tight uploading process, the UPLOAD_COMPLETE_DATA event (Flash Player 9.0.28.0). This event fires after the COMPLETE event and contains an important piece of information. The data property of the DataEvent contains the raw data returned from the server after a successful file upload. Finally, a way to return from the server information about the file and/or process. This is especially useful if during the upload process you need to do additional things like create a database record and then return the new database id, or possibly put the file in a different path based on the user, and return the path where the file exists back to the client.
Here's a quick sample of implementing the new event in Flex and also a Coldfusion and PHP script to upload a file and then output and return data back to the client in a clean consistent fashion.
The Flex code. As you can see, this is a very simple example, you select a file and when the upload has completed the results from the server are output into a text area.
<?xml version="1.0" encoding="utf-8"?>
<!--
Derrick Grigg
derrick@dgrigg.com
http://www.dgrigg.com
created on August 2, 2007
A simple file upload process with data returned from the server
using the UPLOAD_COMPLETE_DATA event.
-->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
public var file:FileReference;
public function selectFile():void
{
file = new FileReference();
file.addEventListener(Event.SELECT, fileSelected);
file.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, uploadDataComplete);
file.addEventListener(Event.COMPLETE, uploadComplete);
file.addEventListener(IOErrorEvent.IO_ERROR, handleError);
file.browse();
}
public function handleError(event:IOErrorEvent):void
{
status_txt.text = 'ERROR: ' + event.text + '\n';
}
public function fileSelected(event:Event):void
{
file = FileReference(event.target);
file_txt.text = file.name;
status_txt.text = 'upload file: '+ file.name + '\n';
var request:URLRequest = new URLRequest();
request.url = "uploader.cfm";
file.upload(request);
}
public function uploadDataComplete(event:DataEvent):void
{
var result:XML = new XML(event.data);
status_txt.text += 'Upload Data Complete\n'
status_txt.text += 'RESULT: ' + result.toString() + '\n'
status_txt.text += 'STATUS: ' + result.status + '\n';
status_txt.text += 'MESSAGE: '+ result.message;
}
public function uploadComplete(event:Event):void
{
status_txt.text += 'Upload complete\n';
}
]]>
</mx:Script>
<mx:VBox>
<mx:TextInput id="file_txt"/>
<mx:Button id="select_btn" label="select" click="selectFile();"/>
<mx:TextArea id="status_txt" width="400" height="200"/>
</mx:VBox>
</mx:Application>
The Coldfusion and PHP scripts upload a file and then output a simple XML string stating if the upload worked. You could easily modify this to return back any additional data you needed. The scripts are very simplified for demonstration purposes, you would definitely want to make them more robust in a production environment.
The Coldfusion upload script.
<cfprocessingdirective suppresswhitespace="true"> <cftry> <cffile action="upload" fileField="filedata" destination="c:\wamp\www\test\flex" nameconflict="overwrite"> <cfxml variable="status"><result><status>OK</status><message><cfoutput>#filename#</cfoutput> uploaded successfully.</message></result></cfxml> <cfcatch> <cfxml variable="status"><result><status>Error</status><message><cfoutput>#cfcatch.Message#</cfoutput></message></result></cfxml> </cfcatch> </cftry> <cfoutput>#status#</cfoutput> </cfprocessingdirective>
The PHP upload script
<?php
$upload_dir = $_SERVER['DOCUMENT_ROOT'] . dirname($_SERVER['PHP_SELF']) . '/';
$upload_url = "http://".$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']) . '/';
$message ="";
$temp_name = $_FILES['Filedata']['tmp_name'];
$file_name = $_FILES['Filedata']['name'];
$file_name = str_replace("\\","",$file_name);
$file_name = str_replace("'","",$file_name);
$file_path = $upload_dir.$file_name;
$result = move_uploaded_file($temp_name, $file_path);
if ($result)
{
$message = "<result><status>OK</status><message>$file_name uploaded successfully.</message></result>";
}
else
{
$message = "<result><status>Error</status><message>Somthing is wrong with uploading a file.</message></result>";
}
echo $message;
?>
You can download the sample files here.
I'm glad to see Adobe finally added this, it makes life so much easier.
Aug 03, 2007 at 5:46 AM
Hi,
The hint is great, but i got one question. Where is the Flash Example?
I see one for Flex and other for Coldfusion, but none for Flash. Maybe the title should be Flex and CF file uploading with return data?
However, let me tell, that you are doing a great job.
Brgds,
CP
Aug 03, 2007 at 7:45 AM
Hey CP, the actionscript in the first code example (the Flex) is all the actionscript that is required to make it work in Flash. The only difference being you would need to create a button and textfield in Flash, but otherwise, you should be able to lift the actionscript straight out and it will work.
Aug 03, 2007 at 11:35 AM
Very helpful. Was just starting to do this myself. Saved me some major time.
Thanks,
Sep 13, 2007 at 4:56 PM
Had trouble using the DataEvent type in AS2, flash couldn't seem to find it using the standard imports, giving error "The class or interface 'DataEvent' could not be loaded"... I don't know if there is a package/library to import that has the class for AS2, but it seems like an AS3 class.
In any case, I got it working with AS2 in Flash CS3 with a slightly different set of arguments in the handler:
var reference:FileReference = new FileReference();
reference.addListener(referenceListener);
// standard flash 8 as2 events:
referenceListener.onSelect = activateUploadButton;
referenceListener.onProgress = updateProgress;
referenceListener.onComplete = finish;
referenceListener.onHTTPError = handleError;
referenceListener.onIOError = handleError;
referenceListener.onSecurityError = handleError;
// * NEW flash player 9 supported event:
referenceListener.onUploadCompleteData = responseHandler;
function responseHandler(fileRef:FileReference, data:String):Void
{
trace("File Sent: " + fileRef.name);
trace("Server's Response: \n" + data);
var response:XML = new XML(data); // parse response into XML object
}
then I think I am going to use the standard XML object onLoad function to trigger handling the response ... something like response.onLoad = doSomethingWithResponse();
Hope that helps any other n00bs trying to catch up on this fileReference event addition..
Sep 13, 2007 at 7:36 PM
The solution I used is purely AS3. I don't believe there is a similiar event in AS2.
Sep 14, 2007 at 3:29 PM
Do you know of a way to compress (gzip) the file bytes during upload to speed up the transfer of large files? I can't find any mention of such in the Flex docs.
Sep 14, 2007 at 7:09 PM
I'm not sure that you can compress before/during upload in Flex. From what I understand the file uploading in actionscript works essentially the same as a multi-part form in HTML. There is not intermediary step where you could compress the file when using this technique in a browser. If you used AIR then you could likely compress the file because you'd have full access to the local system.
Sep 25, 2007 at 12:47 AM
Hi
May i know the java way to upload the file returned from your code
Oct 03, 2007 at 6:49 AM
i'm checking your projects but i can't find web adress more of these web sites which you build it. and http://www.fedexstories.com opening in a few minutes :)
Oct 10, 2007 at 10:09 PM
Thanks for putting this out there, it's exactly what I was looking for!
Oct 11, 2007 at 8:21 AM
This is exactly what I am looking for but when I run the example (using the ColdFusion uploader) I am receiving a TypeError as follows:
TypeError: Error #1088: The markup in the document following the root element must be well-formed.
The xml returning to Flex looks okay, but when I view the data element in the debugger in Flex Builder it has a number of \n \r characters appended to it.
Did anyone else have this issue? I really need to get this working...
Oct 11, 2007 at 8:23 AM
I had problems getting this to work with the ColdFusion uploader. I was getting a TypeError: Error #1088: The markup in the document following the root element must be well-formed in Flex.
To resolve this I had to switch off debugging output in my CF server.
Dec 02, 2007 at 2:42 AM
This works for me, but the upload happens soon as you pick your file. Unless I am missing something ideally you would choose your file first, then click a button to upload.
I like the idea, it just seems weird to me that once I pick the file, the upload starts instantaneouly.
Dec 21, 2007 at 1:14 AM
Awesome, thanks for the info! Exactly what I was looking for.
Jan 13, 2008 at 4:52 PM
I got it work,
this wasnt so hard!
but very effective thanx CP
Jan 13, 2008 at 5:25 PM
@Orla S: I also had problems getting this to work with the ColdFusion uploader. With the examples from this article, it wasn't too difficult to fix after all. Thanks!
Jan 14, 2008 at 4:05 PM
For those interested, there is now a translation at the dutch site LeerWiki.
Mar 18, 2008 at 9:15 AM
thanks so much for posting this. it was a huge timesaver.
Mar 25, 2008 at 2:58 PM
Do you know of a way to compress (gzip) the file bytes during upload to speed up the transfer of large files? I can't find any mention of such in the Flex docs.
Mar 30, 2008 at 3:13 PM
Awesome, thanks for the info! Exactly what I was looking for.
Apr 12, 2008 at 12:48 PM
thanks so much for posting this. it was a huge timesaver.
Apr 17, 2008 at 5:45 PM
Awesome, thanks for the info! Exactly what I was looking for.
Apr 28, 2008 at 6:36 AM
Thnx for the AS2/XML tip Sean Powell,
Exactly what i was looking for !
May 06, 2008 at 6:13 AM
Very very God Code Exmale.
many Many Thanks to u.
Jay Bharat
Php Prtogrammer
Jun 04, 2008 at 6:39 AM
mp3 files are not uploading more than 3 mb. kindly help me
Jun 04, 2008 at 7:26 AM
Ramesh, check your server settings to see what the maximum allowable file size is. 3mb should be fine. This is from the Flex Reference:
Jun 09, 2008 at 10:09 AM
It is a huge timesaver, i am going to use it on
Jun 21, 2008 at 1:35 PM
thanks so much for posting this. it was a huge timesaver
Jul 03, 2008 at 1:52 AM
Everything works fine but I cant find the file in the c:\wamp\www\test\flex directory
I changed the destination to another place but it still doesnt work . Pl. help soon.
Thank you
Jul 03, 2008 at 8:21 AM
John,
Try to return the entire status from the cffile operation to make sure there are no errors. Also, you may want to check the permissions to make sure you can write the file to the directory.
Derrick
Jul 18, 2008 at 9:15 AM
@ Derrick: many times I tried to find an answer to my problems with mp3 files that are not uploading more than 3 mb. I stumbled upon this blog and now it seems to be fixed. Thanks!
Aug 11, 2008 at 6:39 AM
Hi,
I am not able ot upload 6 MB fiel to servelt using flex. I have modified the server.xml in tomcat for maxPostSize but still not working. Please let me know how I can achieve this.
Aug 17, 2008 at 7:32 PM
Awesome, I was planning on writing something like this, looks like I don’t need to!