To use the new FileReference features please read these two articles flexexamples.com and using flashplayer 10
Here are some screenshots of the flex application.
First we can upload a file. The datagrid show the status of the uploaded files.
Off course we can download some files from a remote server. First we need to get a list of the remote files. For this we need to press the Get remote files button.
We can select a file and press the Retrieve File Button. When the status is ready we can save this file by pressing the Save File Button.
Here you can download the Flex source code
The code of the upload panel
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical" width="100%" height="100%"
title="Upload Files">
<mx:Script>
<![CDATA[
import mx.rpc.AsyncToken;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
private var refUploadFile:FileReference;
private var UploadFiles:Array = new Array();
// Called to add file(s) for upload
private function addFiles():void {
refUploadFile = new FileReference();
refUploadFile.browse();
refUploadFile.addEventListener(Event.SELECT,onFileSelect);
refUploadFile.addEventListener(Event.COMPLETE,onFileComplete);
}
// Called when a file is selected
private function onFileSelect(event:Event):void {
UploadFiles.push({ name:refUploadFile.name,
size:formatFileSize(refUploadFile.size),
status:"initial"});
listFiles.dataProvider = UploadFiles;
listFiles.selectedIndex = UploadFiles.length - 1;
refUploadFile.load();
for ( var i:int = 0 ; i < UploadFiles.length ; i++ ) {
if( UploadFiles[i].name == refUploadFile ) {
UploadFiles[i].status = "loaded";
listFiles.dataProvider = UploadFiles;
break;
}
}
}
// Called to format number to file size
private function formatFileSize(numSize:Number):String {
var strReturn:String;
numSize = Number(numSize / 1000);
strReturn = String(numSize.toFixed(1) + " KB");
if (numSize > 1000) {
numSize = numSize / 1000;
strReturn = String(numSize.toFixed(1) + " MB");
if (numSize > 1000) {
numSize = numSize / 1000;
strReturn = String(numSize.toFixed(1) + " GB");
}
}
return strReturn;
}
private function onFileComplete(event:Event):void
{
refUploadFile = event.currentTarget as FileReference;
var data:ByteArray = new ByteArray();
refUploadFile.data.readBytes(data,0,refUploadFile.data.length);
var token:AsyncToken = AsyncToken(
remoteUpload.doUpload(data, refUploadFile.name)
);
token.kind = refUploadFile.name;
for ( var i:int = 0 ; i < UploadFiles.length ; i++ ) {
if( UploadFiles[i].name == refUploadFile ) {
UploadFiles[i].status = "upload";
listFiles.dataProvider = UploadFiles;
break;
}
}
}
private function uploadResultHandler(event:ResultEvent):void
{
for ( var i:int = 0 ; i < UploadFiles.length ; i++ ) {
if( UploadFiles[i].name == event.token.kind ) {
UploadFiles[i].status = "finished";
listFiles.dataProvider = UploadFiles;
break;
}
}
}
private function faultResultHandler(event:FaultEvent):void
{
for ( var i:int = 0 ; i < UploadFiles.length ; i++ ) {
if( UploadFiles[i].name == event.token.kind ) {
UploadFiles[i].status = "error";
listFiles.dataProvider = UploadFiles;
break;
}
}
}
]]>
</mx:Script>
<mx:RemoteObject id="remoteUpload" destination="FileUtils"
result="uploadResultHandler(event)"
fault="faultResultHandler(event)"/>
<mx:Canvas width="100%" height="100%">
<mx:DataGrid id="listFiles" left="0" top="0" bottom="0" right="0"
allowMultipleSelection="true" verticalScrollPolicy="on"
draggableColumns="false" resizableColumns="false" sortableColumns="false">
<mx:columns>
<mx:DataGridColumn headerText="File" width="150" dataField="name" wordWrap="true"/>
<mx:DataGridColumn headerText="Size" width="50" dataField="size" textAlign="right"/>
<mx:DataGridColumn headerText="Status" width="50" dataField="status" textAlign="right"/>
</mx:columns>
</mx:DataGrid>
</mx:Canvas>
<mx:ControlBar horizontalAlign="center" verticalAlign="middle">
<mx:Button id="btnAdd" toolTip="Add file(s)" click="addFiles()"
label="Upload Files" width="150"/>
</mx:ControlBar>
</mx:Panel>
The code of the download panel
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"
width="100%" height="100%" title="Download Files">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.AsyncToken;
private var UploadFiles:Array = new Array();
private var UploadFilesColl:ArrayCollection = new ArrayCollection();
private var fileData:ByteArray = new ByteArray();
private var fileName:String;
private function uploadResultHandler(event:ResultEvent):void
{
if ( event.token.kind == "remoteFileList") {
UploadFilesColl = event.result as ArrayCollection;
for ( var i:int = 0 ; i < UploadFilesColl.length ; i++ ) {
UploadFiles.push({ name:UploadFilesColl[i]
, status:"initial"});
}
listFiles.dataProvider = UploadFiles;
} else {
fileData = event.result as ByteArray;
fileName = event.token.kind;
for ( var b:int = 0 ; b < UploadFiles.length ; b++ ) {
if( UploadFiles[b].name == event.token.kind ) {
UploadFiles[b].status = "Ready";
listFiles.dataProvider = UploadFiles;
break;
}
}
}
}
private function faultResultHandler(event:FaultEvent):void
{
}
private function saveFile(event:Event):void
{
var fileReference:FileReference = new FileReference();
fileReference.save(fileData,fileName);
}
private function getRemoteFiles(event:Event):void
{
var token:AsyncToken = AsyncToken(remoteDownload.getDownloadList());
token.kind = "remoteFileList";
}
private function getDownload(event:Event):void
{
var token:AsyncToken = AsyncToken(
remoteDownload.doDownload(listFiles.selectedItem.name));
token.kind = listFiles.selectedItem.name;
}
]]>
</mx:Script>
<mx:RemoteObject id="remoteDownload" destination="FileUtils"
result="uploadResultHandler(event)"
fault="faultResultHandler(event)"/>
<mx:Canvas width="100%" height="100%">
<mx:DataGrid id="listFiles" left="0" top="0" bottom="0" right="0"
verticalScrollPolicy="on"
draggableColumns="false" resizableColumns="false" sortableColumns="false">
<mx:columns>
<mx:DataGridColumn headerText="File" width="150" dataField="name" wordWrap="true"/>
<mx:DataGridColumn headerText="Status" width="50" dataField="status" textAlign="right"/>
</mx:columns>
</mx:DataGrid>
</mx:Canvas>
<mx:ControlBar horizontalAlign="center" verticalAlign="middle">
<mx:Button id="btnList" toolTip="List remote files"
width="150"
label="Get Remote Files"
click="getRemoteFiles(event)"/>
<mx:Button id="btnRetrieve" toolTip="Retrieve file"
width="150" click="getDownload(event)" label="Retrieve File"/>
<mx:Button id="btnSave" toolTip="Save file"
width="150" click="saveFile(event)" label="Save File"/>
</mx:ControlBar>
</mx:Panel>
The java code
package nl.ordina.flex;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.List;
public class FileUtils {
public String doUpload(byte[] bytes, String fileName) throws Exception
{
fileName = System.getProperty("java.io.tmpdir") + "/" + fileName;
File f = new File(fileName);
FileOutputStream fos = new FileOutputStream(f);
fos.write(bytes);
fos.close();
return "success";
}
public List getDownloadList()
{
File dir = new File(System.getProperty('java.io.tmpdir'));
String[] children = dir.list();
List dirList = new ArrayList();
if (children == null) {
// Either dir does not exist or is not a directory
} else {
for (int i=0; i<children.length; i++) {
// Get filename of file or directory
dirList.add( children[i]);
}
}
return dirList;
}
public byte[] doDownload(String fileName)
{
FileInputStream fis;
byte[] data =null;
FileChannel fc;
try {
fis = new FileInputStream(System.getProperty("java.io.tmpdir") + "/" + fileName);
fc = fis.getChannel();
data = new byte[(int)(fc.size())];
ByteBuffer bb = ByteBuffer.wrap(data);
fc.read(bb);
} catch (FileNotFoundException e) {
// TODO
} catch (IOException e) {
// TODO
}
return data;
}
}
Hello,
ReplyDeletethis is a nice example but i still have a problem with the loadBytes(data) function (on any type of file: xml, txt, ...)
I have the error :
#2124 Loaded file is an unknown type.
Could you help me ?
Hi, I also got this error when I upload the not other files then png, jpg and swf. This is caused by the Loader class. It only support these files.
ReplyDeleteI will change my example
thanks
Just use this code instead of the loader class
ReplyDeleteprivate function onFileComplete(event:Event):void
{
refUploadFile = event.currentTarget as FileReference;
var data:ByteArray = new ByteArray();
refUploadFile.data.readBytes(data,0,refUploadFile.data.length);
Hi,
ReplyDeleteI followed your example and its working great for uploads.
But was not able to download the files.
I was debugging and saw that the fileReference.save(fileData,fileName); is not executed.
The app is stopped at this statement and no other code below this is being executed.
Plz help me over this...
Thanks,
Madan N
Hi,
ReplyDeleteyou have to retrieve the file first and then you can download this.
I don't know to hold the click event ( to retieve async the file with blazeds) and put this on the save action.
can you send me you code
biemond at gmail dot com
thanks Edwin
Greate example but for me
ReplyDelete1 var data:ByteArray = refUploadFile.data and
2 refUploadFile.load();
giving me compiler i am using flex 3.1 can anybody suggest me
Hello Biemond,
ReplyDeletethanks to your example. Do you have an example to anyfiles? Best regards from Brazil!
Great stuff. But one question. Is there a way to trace the upload progress to the server. RemoteObject seem to have fault and result events sent automatically. But what if we want to update a progress bar.
ReplyDeleteThanks!
K.
Hi,
ReplyDeletei'm having some problems putting this example working.....
I'm using BlazeDS, Cairngorm , flash 10, flex sdk 3.3 but i just keep getting error when i try to upload a file.
Besides, in your function onFileComplete(event:Event) you have this "if( UploadFiles[i].name == refUploadFile )". Is this correct? You are trying to compare a refUpload:Filereference with a String.
Please give some ideas to solve my problem.
Thx.
Hi K.
ReplyDeleteI don't know how to monitor the upload progress. I will take a look.
thanks Edwin
Hi
ReplyDeleteCan you send me some more details about your error.
Does the upload start or not. and maybe yoy can send me a testcase
to biemond at gmail dot com
thanks Edwin
This is awesome thank you so much for this. I am getting this error in the code
ReplyDeleteCall to a possibly undefined method load through a reference with static type flash.net:FileReference.
In the Upload.mxml file there is also something similar but for the data in the upload and one about the save in the Download as well.
Hi,
ReplyDeleteWith Actionscript 3 and Flashplayer 10 you can now use the new FileReference features.
To use the new FileReference features please read these two articles flexexamples.com and using flashplayer 10
what version of flex sdk are you using. I am using 3.2 sdk and flashplayer 10
thanks Edwin
Hi. Thank you very much! You really helped a lot.
ReplyDeleteHi,
ReplyDeleteCan I make the same using FP 9?
thanks
Hi,
ReplyDeleteyou need to use fp 10 for this. in 9 you have to use a php script
thanks
private function onFileComplete(event:Event):void
ReplyDelete{
refUploadFile = event.currentTarget as FileReference;
var data:ByteArray = new ByteArray();
==>refUploadFile.data.readBytes(data,0,refUploadFile.data.length);
here am getting error called...access of undefined property data...
what is this ?
Hi
ReplyDeletePlease use Actionscript 3 and Flashplayer 10
thanks Edwin
For all those people who are getting errors like
ReplyDelete1061: Call to a possibly undefined method load through a reference with static type
1061: Call to a possibly undefined method save through a reference with static type
1119: Access of possibly undefined property data through a reference with static type
Go to the Project properties and change the "requires Flash Player version" to 10.0.0.
It would work then.
Unlike the standard way to upload files using servlets, this way doesn't let you to send really big files - just try to upload a 30 Mb (or bigger) file and see what happens.
ReplyDeleteHi,
ReplyDeleteis this a client or server problem.
A server problem can be solved by increasing the memory.
client side then maybe splitting in smaller parts before sending it to the server.
thanks
Hi..
ReplyDeleteI found this example very useful.
Could you please let me know how to upload multiple files with one HTTPService request?
Hi,
ReplyDeleteOk with a HTTPService,
first step is to collect the files and make a object with the selected files as BASE64 and put this over the line. I think you can't do it in 1 action.
thanks
Hi! Thank you very much for the example. Unfortunately I am getting the error:
ReplyDelete[FaultEvent fault=[RPC Fault faultString="No destination with id 'FileUtils' is registered with any service." faultCode="Server.Processing"
please help I have been stuck with this error for a long time
thanks!
Hi,
ReplyDeleteYou need to create the java class and add this reference as remote object in the blazeds configuration located somewhere in your web-inf.
thanks
This comment has been removed by the author.
ReplyDeletethis sample works in the low-capacity otherwise it doesn't work in the massive-capacity at all. is there any method available to let the buffer be used?
ReplyDeleteOk,
ReplyDeleteWhat is the problem, is it flash or the J2EE server. The J2EE server can easily be changed. if it is the client then you need to do a redesign.
By the way, I don't think you should upload big files this way, there are better ways.
thanks
the problem is that i can't upload a massive-capacity file using remote object.
ReplyDeleteit only works in the low-capacity(below 200kb)..
byte[] bytes stands at null in the massive-capacity(over 200mb)..
@RequestMapping("/jsp/FileAttch")
public void boardFileAttch(HttpServletRequest request, HttpServletResponse response )
//blah-blah-blah
int byteCount = 0;
byte buffer[] = new byte[4096];
for(int bytesRead = -1; (bytesRead = in.read(buffer)) != -1;)
{
out.write(buffer, 0, bytesRead);
byteCount += bytesRead;
}
out.flush();
i = byteCount;
//yadda-yadda-yadda
}
thus if i use usual method, i have to send input data using remoteobject after file upload is over
i just want to do it at the same times
Sorry, my English is not very good!
Hi Edwin.
ReplyDeleteIt really works, thank you very much from Colombia.
Thank you for this wonderful example. It worked :)
ReplyDeleteI have a question. Is there any other way to upload / download a file without using the Byte[]. Like data streaming over BlazeDS ? It would be great if you can throw some light over it.
Hi Edwin.
ReplyDeleteA very good article. Just want to know how to change the directory (java.io.tmpdir) to application root directory like (applicationname/assets)
For to show the file upload progress, during uploading (if you are uplodaing a big file, because small size file will upload very fast.
ReplyDeleteput this in your addFiles() in this example or which isy your method intializing the file referece.
refUploadFile.addEventListener(ProgressEvent.PROGRESS, progressFileHandler);
then add this method to
private function progressFileHandler(event:ProgressEvent):void {
pbrUploadProgress.setProgress(event.bytesLoaded, event.bytesTotal);
}
here pbrUploadProgress is a progressbar component of flex ok
Hi this can be done when you use _refUploadFile.upload method.
Deletebut when we use remote object to send the image as byte array to server case will be somewot different.
I dont know even ow to update progress bar in that case. Please suggest if you have a solution.
hi, i would like to know how to use a progress bar. Seems like the event that should drive this issue isn't being dispatched. I've try using a manual dispatching but for some reason the evetn.byteTotal and event.byteLoad seens not to have any value.
ReplyDeleteThanks for your help in advance
A very good article. Just want to know how to change the directory (java.io.tmpdir) to application root directory like (applicationname/assets)
ReplyDeleteGreat example! Thanks!
ReplyDeleteI am sending ByteArray similarly as above but getting an Error,
"Creation validation for class '[B' failed."
***Any pointers to resolve the issue will be a great help.***
[BlazeDS]Serializing AMF/HTTP response
Version: 3
(Message #0 targetURI=/2/onStatus, responseURI=)
(Typed Object #0 'flex.messaging.messages.ErrorMessage')
headers = (Object #1)
rootCause = null
body = null
correlationId = null
faultDetail = null
faultString = "Creation validation for class '[B' failed."
clientId = null
timeToLive = 0.0
destination = null
timestamp = 1.328734836964E12
extendedData = null
faultCode = "Client.Message.Encoding"
messageId = "4C5DF944-A409-A4DA-EB2D-5D00246EF874"
More logs:
[BlazeDS]Creation validation for class '[B' failed.
flex.messaging.io.SerializationException: Creation validation for class '[B' failed.
at flex.messaging.util.ClassUtil.validateCreation(ClassUtil.java:347)
at flex.messaging.io.amf.Amf3Input.readByteArray(Amf3Input.java:507)
at flex.messaging.io.amf.Amf3Input.readObjectValue(Amf3Input.java:213)
at flex.messaging.io.amf.Amf3Input.readObject(Amf3Input.java:130)
Hi
ReplyDeleteI have an application deployed on a remote machine.In that application I have a feature in which I can upload my local files to a folder of that machine.I tried with the SFTP.If my tomact server is in local then I able to upload the files from local to the remote machine.Its not working if my tomcat is deployed in the remote itself .Can you pls help me on that ?