Uploading a file with Adobe Flex to a Java Servlet

8 05 2009

This post is about uploading a file using an Adobe Flex application to a Java Servlet using Apache Commons’ FileUpload.

Adobe Flex application

Let’s start with the Adobe Flex application. This application is quite simple and can be found in any tutorial about Adobe Flex’s capability of uploading files. The code below is all one needs.

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” layout=”vertical”><mx:Script>
<![CDATA[
import flash.net.FileReference;

private var fileRef:FileReference = new FileReference();
private var servletTarget:URLRequest = new URLRequest("<your servlet's location comes here>");

private function fileBrowse():void {
fileRef.addEventListener(Event.SELECT, onSelect);
fileRef.addEventListener(ProgressEvent.PROGRESS, progressHandler);
uploadStatus.text = "Browsing the File System";
fileTitle.text = "";
description.text = "";
fileLocation.text = "";
fileRef.browse();
}

private function onSelect(event:Event):void {
uploadStatus.text = "File selected";
fileLocation.text = fileRef.name;
}

private function progressHandler(event:ProgressEvent):void {
var percentLoaded:Number = Number((event.bytesLoaded / event.bytesTotal) * 100);
uploadStatus.text = "The file is " + percentLoaded + "% loaded";
}

private function fileUpload():void {
uploadStatus.text = "Uploading....";
var menuURLVars:URLVariables = new URLVariables();
menuURLVars.fileTitle = fileTitle.text;
menuURLVars.description = description.text;
servletTarget.method = URLRequestMethod.POST;
fileRef.upload(servletTarget);
}
]]>
</mx:Script>

<mx:Panel title=”Uploader”>
<mx:Text text=”Manual:&#xd;Step 1. Enter a title for the file&#xd;Step 2. Enter a description for the file&#xd;Step 3. Click the ‘Browse’ button to search the file that one wants to upload&#xd;Step 4. Click the ‘Upload’ button to upload the file to the server” width=”100%”/>
<mx:Form>
<mx:FormItem label=”File title” required=”true”>
<mx:TextInput id=”fileTitle” width=”300″/>
</mx:FormItem>
<mx:FormItem label=”Description” required=”true”>
<mx:TextArea id=”description” width=”300″/>
</mx:FormItem>
<mx:FormItem label=”File to upload” direction=”horizontal” required=”true”>
<mx:TextInput id=”fileLocation” width=”300″ editable=”false” color=”#001234″/>
<mx:Button id=”browseButton” label=”Browse” click=”fileBrowse()”/>
</mx:FormItem>
<mx:FormItem label=”">
<mx:Button id=”uploadButton” label=”Upload” click=”fileUpload()”/>
</mx:FormItem>
<mx:FormItem label=”Upload status”>
<mx:Label id=”uploadStatus” text=”Select a file to upload”/>
</mx:FormItem>
</mx:Form>
</mx:Panel>

</mx:Application>

Code 1: uploader.mxml

As one can see in the code above, all one needs is an instance of the flash.net.FileReference class. In this example we use its method browse to open a file browse dialog at the client side and its method upload to upload the selected file to the servlet, which location is specified by an instance of the flash.net.URLRequest class. Because we want to upload a file, we need to set the URLRequest’s attribute method to URLRequestMethod.POST and pass the URLRequest instance to the FileReference’s method upload, when starting to upload the file.

Java Servlet

In this example we use the Eclipse IDE.

On the server side we need to implement a Java servlet, which will handle the uploaded file by the Adobe Flex application. We start by creating a new Dynamic Web Project in Eclipse. In the source folder we add a new class ProcessFileUpload, which extends HttpServlet and belongs to the package flex.samples.servlets. The source code for the class ProcessFileUpload is shown below.

package flex.samples.servlets;

import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.util.List;
import java.util.Iterator;

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

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

/**
* This class provides functionality to handle an uploaded file.
* This class uses code provided by Apache
*
* @author geert.zijlmans
*
*/
public class ProcessFileUpload extends HttpServlet {

private static final long serialVersionUID = 1L;

/**
* Default constructor.
*/
public ProcessFileUpload() {
// TODO Auto-generated constructor stub
}

/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doPost(request, response);
}

/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
// Check that we have a file upload request
boolean isMultipart = ServletFileUpload.isMultipartContent(request);

if (isMultipart) {
// Create a factory for disk-based file items
FileItemFactory factory = new DiskFileItemFactory();

// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);

// Parse the request
List /* FileItem */ items = upload.parseRequest(request);

// Process the uploaded items
Iterator iter = items.iterator();
while (iter.hasNext()) {
FileItem item = (FileItem) iter.next();

if (item.isFormField()) {
processFormField(item);
} else {
processUploadedFile(item);
}
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}

private void processFormField(FileItem item) {
String name = item.getFieldName();
String value = item.getString();
System.out.println(“Item name: ” + name + ” ; value: ” + value);
}

private void processUploadedFile(FileItem item) throws Exception {
String fieldName = item.getFieldName();
String fileName = item.getName();
String contentType = item.getContentType();
boolean isInMemory = item.isInMemory();
long sizeInBytes = item.getSize();

boolean writeToFile = true;
if (sizeInBytes > (5 * 1024 * 1024)) {
writeToFile = false;
}
// Process a file upload
if (writeToFile) {
File uploadedFile = new File(“<directory on the server’s file system>“+ fileName);
if (!uploadedFile.exists()) {
uploadedFile.createNewFile();
}
item.write(uploadedFile);
}
else {
System.out.println(“Trying to write a large file.”);
}

}
}

Code 2: ProcessFileUpload.java

After creating the class ProcessFileUpload we need to make it visible as a servlet. To make this servlet visible we need to change the contents of the web.xml file. The change is shown in bold in the example below.

<?xml version=”1.0″ encoding=”UTF-8″?>
<web-app id=”WebApp_ID” version=”2.4″ xmlns=”http://java.sun.com/xml/ns/j2ee” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=”http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd”>
<display-name>
my-servlet</display-name>

<servlet>
<description>
</description>
<display-name>ProcessFileUpload</display-name>
<servlet-name>ProcessFileUpload</servlet-name>
<servlet-class>flex.samples.servlets.ProcessFileUpload</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ProcessFileUpload</servlet-name>
<url-pattern>/ProcessFileUpload</url-pattern>
</servlet-mapping>

<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>

Code 3: web.xml

If one wants to compile this Dynamic Web Project, one will need to add the following API’s to the classpath of the project:

After exporting the project as a .war file one can deploy this .war file on one’s Web Application Server (e.g. JBoss).

Testing the solution

The servlet should be active now, so let us test our Adobe Flex application by running it in Adobe Flex Builder 3 Pro. The output in de browser should look like the picture below.

Uploader Flex Application

Uploader Flex Application

One now can enter a file title, enter a file description, point to a file to be uploaded and finally upload the file to the servlet.

This was all :)


Actions

Information

9 responses

3 07 2009
nina010101

Hi!
Thanks for this very intresting tutorial.
In fact, I want to ask you about a problem I’m facing with flex, Servlets and Glassfish V3.
When I execute deploye the servlet, it gets the informations from a form in order to generate a report with Jasperrepots. And this when Glassfish shows an “Error: null” error.
I really don’t know what is causing that problem..:s
Help pleaaaaaaaaaase!!
And thanks in advance.

4 07 2009
geertzijlmans

Hi Nina,

Could you provide me with the stacktrace of the Glassfish log and your servlet’s code?

Regards,

Geert

4 07 2009
nina010101

Hi Geert,
First, thanks for replying. It’s very kind of you.
Here is My servlet code:

public class GetDataServlet extends HttpServlet {

protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType(“text/html;charset=UTF-8″);
PrintWriter out = response.getWriter();
try {

String nom = request.getParameter(“nom”);
String prenom = request.getParameter(“prenom”);
String profession = request.getParameter(“profession”);
String date = request.getParameter(“date”);
String email = request.getParameter(“email”);
String telp = request.getParameter(“telp”);
String telpro = request.getParameter(“telpro”);

System.out.println(nom+” “+prenom+” “+profession+” “+date+” “+email+” “+telp+” “+telpro);
if (nom == null) {
out.println(“false”);
} else {
out.println(“true”);
GenerateReport rep = new GenerateReport();
rep.Generate(nom, prenom, profession, date, telpro, telp);

}

} catch (Exception x) {
System.out.println(“Error: ” + x.getMessage());
} finally {
out.close();
}
}

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

@Override
public String getServletInfo() {
return “Short description”;
}

}

And here is the Generate methode code:

public class CompileReport {

public void Generate() throws JRException{

Map parameters = new HashMap();
parameters.put(“nom”, nom);
parameters.put(“prenom”, prenom);
parameters.put(“profession”, profession);
parameters.put(“date”, date);
parameters.put(“email”, email);
parameters.put(“telp”, telp);
parameters.put(“telpro”, telpro);
JasperFillManager.fillReportToFile(“C:\\Users\\Naoual\\Documents\\NetBeansProjects\\EasyBplan\\rapports\\rapport.jasper”, “C:\\Users\\Naoual\\Documents\\NetBeansProjects\\EasyBplan\\rapports\\rapport.jrprint”,parameters,new net.sf.jasperreports.engine.JREmptyDataSource());
JasperExportManager.exportReportToPdfFile(“C:\\Users\\Naoual\\Documents\\NetBeansProjects\\EasyBplan\\rapports\\rapport.jrprint”, “C:\\Users\\Naoual\\Documents\\NetBeansProjects\\EasyBplan\\rapports\\rapport.pdf”);

} }

5 07 2009
geertzijlmans

Hi Nina,

Shouldn’t this GenerateReport rep = new GenerateReport(); be CompileReport rep = new CompileReport();?
And try to use x.printStacktrace() instead of System.out.println(”Error: ” + x.getMessage());. This will give you more information about what went wrong and also the position in your code where it went wrong.

Regards,

Geert

4 07 2009
nina010101

I forgot to tell you that the error disappears when I murge the methode with the servlet. So, I guess the error occurs when the servlet calls the methode.
Concerning the log file, it contains nothing. :s

Thanks again :) !!!

5 07 2009
geertzijlmans

Hi Nina,

Are both classes in the same package? If not the servlet class must have an import-statement of the CompileReport class.

Regards,

Geert

5 07 2009
nina010101

Hi Geert,
I use a .jasper (a .jrxml that I have already compiled) that’s why I call directly GenerateReport rep = new GenerateReport();.

The 2 calsses were not at the same package but I’ve added the import statement.
import easybplan.reporting;

Regards,
Nina

13 08 2009
Josh

Does this sample application upload large files? Or is it limited to the post_max_file_size (typically between 3-8MB)?

The post_max_file_size on my server is 8MB… I need to upload files that are between 3MB to 100MB in size… Will this solution work for me?

14 08 2009
geertzijlmans

Hi Josh,

Recently we’ve implemented this solution for a client of ours. Their request was to have an upload limit of 250 Mb. This solution handles this amount of data in chunked message parts, which are received by the HTTP servlet. Remember that this solution only works for 250 Mb when you have set the timeout of the Web Application Server large enough. Also don’ t try to convert the InputStream of the data above a certain amount of Mb’s (in our case 248,5 Mb) to a byte[], because your JVM will throw a Java Heap Out of Memory exception when you do so.
If you use a database like Oracle, try to insert it into a Blob or when using MySQL a LargeBlob.
I haven’t used the post_max_file_size on my Web Application Server. But when it’s possible to alter this value, you might need to do this.

Regards,

Geert

Leave a comment