Devel Blog – CoPLaS

Blog about things, I'm currently interested in. Now Android, Grails, jQuery and Java.

About me

Developer from Slovak Republic, EU. Currently interested in Java, Grails and Flex.

CV - Curriculum Vitae

In Flash player it was possible until version 10 to upload files only by FileReference.upload method (there were some ugly hacks – such as uploading in external iframe).

Uploading files using directly FileReference.upload has some serious problems problems. Especially on Firefox, Flash player plugin creates it’s own request (different UserAgent, session and so) so on server it is handled in different session. All the parameters has to be sent, or some hacks has to be done (I manually set the jsessionid to each request).

And after all known hacks, it has still some serious problems using SSL – if the certificate is not validly imported to client machine, it just crashes without asking, if it has to trust it and so. See bugs:

Since v. 10 (and Flex 4), there is possibility to read local files directly, so I decided to try to upload files not using FileReference.upload method. But to read data as ByteArray and send it as POST request to server.

I found interesting class -UploadPostHelper in this article. Next I merged that example with my old code – browse for file and changed the method from FileReference.upload to FileReference.load. Server is java servlet using apache commons FileUpload – saves file to temp folder and sends XML response – all form items from post request and file uploaded – name and absolute path.

Adobe has changed security in flash player 10, it is impossible to send files in background (probably all requests now needs user interaction). It has to be in some user-action (click…) event handler, so I have two buttons, one for browse for a file, one for upload. Using just method that handles Event.COMPLETE (FileReference) causes Security sandbox violation.



Here is my Client code (UploadTest.mxml):
[code lang="actionscript"]


import mx.controls.Alert;

static public const SERVER_URL:String = "http://localhost:8081/flash10upload/servlet/FlexUpload";

private var fileReference:FileReference = new FileReference();

private function onLoad():void {
fileReference = new FileReference();
var myFilter:FileFilter = new FileFilter("Text","*.txt");
fileReference.browse([myFilter]);
fileReference.addEventListener(Event.SELECT,onFileSelect);
fileReference.addEventListener(Event.COMPLETE,onFileComplete);
}

private function onFileSelect(event:Event):void {
fileReference.load();
}

private function onFileComplete(event:Event):void {
Alert.show("File Loaded, click upload...");
uploadBtn.enabled = true;
}

private function upload():void {
var byteArray:ByteArray = new ByteArray();
var fileName:String = fileReference.name;
var uploadPath:String = SERVER_URL;
var parameters:Object = new Object();
parameters.test = "test1";

fileReference.data.readBytes(byteArray,0,fileReference.data.length);

var urlRequest:URLRequest = new URLRequest();
urlRequest.url = uploadPath;
urlRequest.contentType = 'multipart/form-data; boundary=' + UploadPostHelper.getBoundary();
urlRequest.method = URLRequestMethod.POST;
urlRequest.data = UploadPostHelper.getPostData(fileName, byteArray, parameters);
urlRequest.requestHeaders.push( new URLRequestHeader( 'Cache-Control', 'no-cache' ) );

var urlLoader:URLLoader = new URLLoader();
urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
urlLoader.addEventListener(Event.COMPLETE, onComplete);
urlLoader.addEventListener(IOErrorEvent.IO_ERROR, onError);
urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onError);
urlLoader.load(urlRequest);
}

private function onComplete(eventObj:Event):void {
var ldr:URLLoader = eventObj.currentTarget as URLLoader;

Alert.show(ldr.data , "complete");
}

private function onError(eventObj:ErrorEvent):void {
Alert.show("onError");
}

]]>







[/code]




Here is my Server code (FlexUploadServlet):
[code lang="java"]
package sk.pavlasek.flash10Upload.web;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.log4j.Logger;

public class FlexUploadServlet extends HttpServlet {

private static final long serialVersionUID = 4588660828164350807L;

private static final Logger log = Logger.getLogger(FlexUploadServlet.class);

public void doPost(HttpServletRequest req, HttpServletResponse res)
throws UnsupportedEncodingException {
res.setDateHeader("Expires", -1);
res.setDateHeader("Last-Modified", System.currentTimeMillis());
res.setHeader("Pragma", "");
res.setHeader("Cache-Control", "");

req.setCharacterEncoding("UTF-8");
res.setCharacterEncoding("UTF-8");

File disk = null;
FileItemFactory factory = new DiskFileItemFactory();
List items = null;
ServletFileUpload upload = new ServletFileUpload(factory);
ServletOutputStream out = null;

try {
res.setContentType("text/xml");
out = res.getOutputStream();
out.println("");

items = upload.parseRequest(req);
for (FileItem item : items) {

if (item.isFormField()) {
out.println(" + "\" value=\"" + item.getString() + "\" />");
} else {
String tempdir = System.getProperty("java.io.tmpdir");

if (!(tempdir.endsWith("/") || tempdir.endsWith("\\"))) {
tempdir = tempdir + System.getProperty("file.separator");
}

String fileName = tempdir + item.getName();
disk = new File(fileName);
item.write(disk);
log.debug(disk.getAbsolutePath());

out.println("");
out.println("" + item.getName()
+ "
");
out.println("" + disk.getAbsolutePath() + "");
out.println("
");
}
}
out.println("");
out.close();
} catch (FileUploadException fue) {
fue.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}

[/code]



Download:

5 Responses to “Flex 10 – upload files using URLRequest”

  1. It’s very useful about how to use Flex and Java to upload images.Good…

    Chandra

  2. This has helped me a lot. Thank you.

    Yoosaf

  3. Thank you very much! The source codes solve my problem.

    Actually I have been facing a problem with FileReference upload and NTLM authentication.

    Shen Rendao

  4. Can you explain why you’ve got this on the request:

    urlRequest.requestHeaders.push( new URLRequestHeader( ‘Cache-Control’, ‘no-cache’ ) );

    and then this on the response from the servlet:
    res.setHeader(“Cache-Control”, “”);

    Having some SSL issues so curious to know whether this is related. Thanks.

    TA

  5. @TA: I did this long tome ago :) so as far as I remember it was “tuned to work” after many hours of try/fix – try again… And IE ignored some cache settings, so I finished after it was OK in IE and FF…

    admin

Leave a Reply