Preorder Estimated Availability Date. Your credit card will not be charged until the product is shipped. Estimated availability date is subject to change.Preorder Estimated Availability Date. Your credit card will not be charged until the product is ready to download. Estimated availability date is subject to change.

User level

Required products

Sample files

Additional Requirements

Apache Commons FileUpload Package

File uploads enabled by Flex and Java provide a high level of interaction between the user and a web application. For example, people can use file upload to submit a résumé to a job posting or a home movie to a video sharing site. Flex offers a powerful library of tools to handle file uploads, while also providing feedback to the user on the upload’s progress.

For the server-side processing, a simple Java servlet can receive the request and write the file to storage. The request can contain additional data, providing more complex instructions to the servlet. In response, the servlet can generate XML for Flex to display the upload’s status.

This article shows how to develop a Flex and Java file upload mechanism for attaching images to an employee list. In the process, it demonstrates Flex’s ECMAScript for XML (E4X) language extension, custom components, classes, and events, as well as a Java-like properties file. In addition, the article explains packages in Java for generating XML.

Creating the Flex project

The sample Flex application for this article will display a DataGrid control containing a few employees, with the option to browse for and upload a photo for each person. The Flex application sends to the Java servlet a POST request, which includes not just the image file but also the employee ID. The servlet uses the employee ID as the filename, deletes any previous pictures for that employee, writes the image to disk, and responds to Flex with an XML document. In turn, Flex displays the newly uploaded image along with the server’s response.

To start, create a new project in Flex Builder named FileUpload. Begin by adding a few components: a VBox, a Form, and a DataGrid. The Form will display the server response while the DataGrid will list each employee’s name, ID, department, location, and photo.

Note the last column in the grid with ID imageCol; this will hold the image upload component you’ll create later. For now, preview the app to see what you have (see Figure 1).

Figure 1. The Flex app without any data.

Using a custom XML configuration file

To simplify deployment to production, you can use a custom XML file to store server paths and other application-level variables. The values aren’t hardcoded inside the app; instead they’re in a text file that can be easily changed. You only have to modify this one file instead of changing your Flex app and recompiling.

Create an assets folder at the root of your app; right-click it and choose New > File. Name the file properties.xml. The app will use two values that change from development to production: the path to the servlet and the path to the server’s upload folder. They’re named UploadHandler and UploadFolder, respectively.

A few things to note in the above code: The resultFormat property of the HTTService call is set to “e4x”, short for the ECMAScript for XML (E4X) language extension. This format provides straightforward access to the XML document, without the need to convert it to an ArrayCollection. To fetch the value element of the node with the name equal to UploadHandler, you use the following code:

Also note that the variables’ types are set when they’re declared. For example, uploadServletUrl is of type String. This is an example of early (static) binding; the Flex compiler knows the properties and methods of the object at compile-time. This can have dramatic performance benefits. In contrast, with late (dynamic) binding, you declare the variable as a generic type (such as Object) and then set the specific type at runtime. Though more flexible, the latter technique has a performance penalty.

Don’t forget to change the Application tag to call the new handleCreationComplete() method:

Don’t worry about the paths in the properties.xml file now; as you create the Java servlet, you can modify the paths. The Java servlet is relatively simple to create, too. It receives the file from Flex and writes it to disk.

Creating the Java servlet

Java code can be edited with something as simple as a text editor or as sophisticated as the free Eclipse IDE. The server code for this app can be compiled for the older Java 1.4 or the latest versions; I’ll cover the differences as the code is introduced.

Though not required for the simple XML response this servlet provides to Flex, learning an efficient XML generation technique can help you when you need to convert large data sets. The same mechanism can be applied to a few records or to thousands; the results are produced very quickly and efficiently.

To start writing the server code, create a new class file in your favorite Java editor, naming it UploadHandler.java. Type the following into the file (remember to change the package name to reflect your organization!):

The UploadHandler.java code begins by importing some necessary classes. It proceeds to extend the HttpServlet class (thus the presence of the init() method). The doPost() method does the heavy lifting. It receives the Flex HTTP request and generates valid XML in response. But it doesn’t use the usual out.println() method to emit XML; it uses a more efficient means of producing the output, which I’ll cover shortly.

Note that Flex sends additional fields with the file upload. The first item from Flex is Filename, automatically added to the HTTP request header when uploading a file. The last item is another field that Flex adds automatically to the HTTP request header: Upload, the value for the upload button.

Also note the DOCTYPE declaration that references a custom Document Type Definition (DTD) file. In the Java app’s root folder, create a file called response.dtdand place the following content in it:

·The document must have an element called response, which can have 0 or more elements called field and file.

·The field and file elements will contain parsed character data (PCDATA).

·Both the file and field elements must contain an id attribute of type character data (CDATA).

The servlet generates valid XML using the DTD document. But how? In the UploadHandler.java code, you begin by setting the response’s content type to XML and declaring some variables used throughout the code. Then you fetch the path to the upload folder from the web.xml file and store it in the string variable uploadDirectory. Note that the code uses one large try..catch block to handle exceptions. You can modify this as per your requirements.

Now you can instantiate an ArrayList of strings to store the allowed image types and create some Apache FileUpload components. The TransformerHandler declaration begins the XML output processing. This class is part of the Java JAXP (Java API for XML Processing) package for parsing and producing valid XML. For Java 1.4.2 and earlier, you had to download the package separately; with JDK 5.0 and higher, it is an integrated part of Java. To learn more about JAXP, visit the JAXP page.

The SAXTransformerFactory object represents one of the parsing interfaces provided by JAXP. Because SAX (Simple API for XML) doesn’t create an in-memory representation of the XML document, it’s faster and more memory-efficient than the other JAXP interfaces.

Proceed by creating a list of the items in the upload request and fetch the list’s iterator. You can then create a Transformer object to serialize the data and set some output properties on it. Note that you set the DOCTYPE_SYSTEM to the response.dtd file to ensure the output is valid XML:

Then start the XML document with the startDocument() method and instantiate a new AttributesImpl object. This object adds attributes to the XML document’s elements.

The root node of the XML document is response, which has no attributes; thus you can pass the blank attributes object to the startDocument() method. Iterate over the request items list by first clearing the attributes object for reuse. Then convert the current item to a FileItem for processing.

If it’s an HTML form field and its name equals employeeid, you retrieve the employee ID, which Flex passes as part of the HTTP request. Add element attributes and start a field node. To set the tag’s text, use the characters() method and fetch the item’s getString() method:

If the item is something other than a form field, then it is the uploaded file. You only want images uploaded so use an ImageInputStream to read the file’s internal format name. You can also parse the uploaded file’s name and detect its extension, but that is less reliable. Comparing the results of getFormatName() on the ImageReader object to the allowedFormats ArrayList dependably limits the input types.

Set the filename in newFileName based on the employee ID and the image format. If you’ve received an allowed image type, you instantiate a FileFilter object based on the FileFilter.java custom class. This class has an accept() method that returns a Boolean to indicate if the file meets your criteria; in this case, it checks the file’s name to see if it begins with the employee ID and ends with one of the allowed image format extensions. You’ve only uploaded allowed types, so using the file’s extension is very dependable in this case.

The FileFilter object will be used to find and delete any previous images for the employee. Set the employee ID and the allowed image types on the FileFilter object and fetch the list of files from the upload directory based on the filter:

File fileList[] = (new File(uploadDirectory)).listFiles(fileFilter);

Iterate over the list and delete any files that meet the criteria. Now you can write the file to disk. To provide feedback to the user that the upload was successful, you set a status message and concatenate the date/time to it using an instance of the Calendar object:

Dispose of the ImageReader and close the ImageInputStream. Then add the attributes and write the file node to the XML document. Don’t forget to end the response element, end the document, and close the output.

The servlet uses a custom utility class to filter the files on the server’s upload directory and delete any previous pictures for the employee. This class is based on the java.io.FilenameFilter class. Create a new class in your Java app called FileFilter.java and enter the following code:

You’re setting two Boolean variables: startsWith and endsWith. You acquire an iterator from the _imageTypes ArrayList and loop to see if the filename ends with one of the allowed extensions. The accept() method returns true only if both variables are true.

Java servlets use the web.xml file, found in the WEB-INF folder. For this app, you can start with the following code and modify it to meet your needs:

Note that the servlet named UploadHandler is accessed via the URL /uploadhandler(directly from the root of your app); UploadHandler in turn references org.unctv.fileupload.UploadHandler, which represents the package hierarchy and will be different for your app.

You can now compile both Java classes and return to the Flex app.

Adding data to the Flex app

In Flex, to abstract the data from the view (presentation layer), you will use an XMLListCollection for the DataGrid control’s data provider. Data abstraction, an important concept in object-oriented programming, separates the properties of the data from its implementation. As a result, the implementation can change without affecting the properties (interface) visible to the data consumer (UI).

Modify the script block to read the XML employee data and bind it to the DataGrid:

In the above code, a Sort object instance named sortAsc (for sort ascending) provides sorting functionality for the XMLListCollection data. Calling the refresh() method triggers the function. Because the collection object is declared as [Bindable], the DataGrid will automatically receive the data.

Also note the call to the loadEmployeeList() method from the ResultEvent handler. Because of the asynchronous nature of Flex, this ensures that the app only sets the grid’s data when the properties.xml file has successfully loaded; all those variables are set properly before proceeding—thus preventing null reference exceptions.

Run the app to see the employees loaded into the DataGrid (see Figure 2). You’ll notice a small up arrow in the “Name” column header, which indicates that the data has been sorted in ascending order on that column.

Figure 2. Application with the employee data.

Creating the Flex upload component

Remember the imageCol DataGrid column you created earlier? You will place the custom itemRenderer for the file uploads in this column.

In Flex Builder, create a new component and name it ImageUpload. Base it on the HBox component and clear the width and height properties. Edit the ImageUpload.mxml file to add these components in the HBox:

The Image control will display the photo. You bind its source to a variable named imageSrc and handle the IO errors via the imageIOErrorHandler() method. Next to the image, a VBox will display a read-only TextInput. Two buttons side-by-side (inside the HBox control) provide the browse and upload capabilities. Note that the upload button is hidden for now. Rounding out the controls, a ProgressBar will display the upload status using an event listener on the FileReference object.

The functionality of the component comes from the following script block, which you can add inside the top-level HBox control:

In the above code, the creationCompleteHandler() method, called from the creationComplete event of the main HBox control, instantiates a FileReference object and sets its event listeners. The method also fetches the upload folder’s path from the parent document (set from the properties.xml file). You limit the file types the user can choose to the common Web image formats using a FileFilter object:

The first argument to the FileFilter constructor is what the user sees in the “Files of type:” dropdown control in the browse dialog box. The second argument specifies what files on the user’s system are shown in the file-browsing dialog box when the FileReference.browse() method is called.

The browseHandler() method is called when the Browse button is clicked. It sets the visible attributes of the ProgressBar and the upload Button to false before invoking the FileReference.browse() method with the FileFilter object as argument. File selection by the user calls the selectHandler() method, which sets the TextInput to the chosen filename and toggles the Upload button’s visibility to true.

When the file is opened for upload, you use the openHandler() event listener to set the ProgressBar’s visibility and label. Note the label’s text:

pbrUploadProgress.label = "Uploading %3%% of image file.";

The label property lets you include special characters in the label text string. The %3 string represents the percent loaded while %% corresponds to the % sign. For example, the above label would generate the following string:

Uploading 95% of image file.

The uploadHandler() event listener fetches the Java servlet’s path from the parent document and instantiates a URLRequest object with that address. You can use POST as the HTTP request method and pass the employee’s ID as a URLVariable to the URLRequest’s data property. Then toggle the visibility of the ProgressBar to true and call the FileReference.upload() method with the URLRequest argument. The method invocation uploads the selected file to the specified URL along with the employee ID.

To update the ProgressBar, you employ the progressHandler() event listener method. It receives the FileReference’s ProgressEvent and passes the bytesLoaded and bytesTotal values to the ProgressBar.setProgress() method to reflect the upload progress.

When the upload completes successfully, you invoke the uploadCompleteHandler() method. Within a try..catch block, you store the servlet’s response as an XML object, set the ProgressBar’s label, and change the value of the imageSrc variable to the URL of the uploaded file. Because the variable is defined as [Bindable] and the Image control’s source is bound to it, the Image control will display the new photo upon completion of the upload.

If the upload fails with an input/output (IO) error, it will call the uploadIoErrorHandler() method to change the ProgressBar’s label and show an Alert box with the error.

The Image control can invoke an error handler when the specified file isn’t found. You define the imageIOErrorHandler() method as the IO error event listener:

The method sets the TextInput control’s text to an error message and displays a placeholder image called missing.jpg, found in the upload folder. To see this in action, override the set data() method of the itemRenderer, and set the imageSrc variable to “noimage.jpg”. Because there isn’t an image called noimage.jpg, it will call the method when the page first loads.

Now you can add this custom component to the DataGrid control’s imageCol column in the FileUpload.mxml file. Open this file and edit the DataGrid to reflect the following change:

Note that you’re specifying the package hierarchy to the component in the itemRenderer property. Run the Flex app to see how the page looks (see Figure 3):

Figure 3. Application with the ImageUpload component.

Creating a custom Flex event

One question remains: How do you let the parent document know the servlet’s response? Simple: Use a custom Flex event to communicate with the main Application.

You created a Form with some controls to display the reply. Now add the code necessary to fill it with the server response. Create a new class named UploadEvent; in the New ActionScript Class dialog box, provide the package name and choose flash.events.Event as the Superclass. Place the following code in the UploadEvent.as file:

The event type is defined in the public static constant variable UPLOAD_EVENT. The two private member fields will hold the server response. In the class constructor, set the default values for the two Boolean variables in the argument declaration. The bubbles and cancelable arguments determine whether the event bubbles up through the object hierarchy and if the event can be cancelled, respectively:

You need to have the event bubble up the chain, out of the custom component and to the Application, where it can be detected and handled. Set the bubbles default value to true; the cancelable Boolean can be left as false. The super() method call invokes the superclass constructor of this class with the specified arguments. Finally, the getter and setter methods match the private member fields and provide a public interface for the class.

Now wire up the custom component to fire the event. Add the following metadata tag just above the script block in the ImageUpload.mxml file. This defines the MXML property for the event and the data type of the event object that this component emits:

You declare a variable of type UploadEvent and instantiate it using the custom event’s constructor. Note that you only have to indicate the event’s name; the constructor will use the default values for the other two arguments (bubbles and cancelable) provided within the class.

Then you use the public properties of the custom event to store the server response. The servlet’s response XML includes the file element, with the status message indicating successful upload plus the date/time stamp. Use this value for the ServerResponse property of the custom event, while storing the entire servlet XML response in the ServerResponseRaw property.

Finally, call the dispatchEvent() method to trigger the event. Because there is no event handler defined within the ImageUpload component and the custom event is set to bubble, it will travel up the object hierarchy.

The main Application page, FileUpload.mxml, needs to listen to and capture this event. To do so, modify the FileUpload.mxml file’s handleCreationComplete() method to add an event listener to the Application:

You’re almost ready to see the app in action. One final step: Ensure the Flex app’s custom properties.xml file contains the correct paths to your Java servlet and the server’s upload location.

Run the Flex app, click the Browse button for any of the employees in the DataGrid, and select an image file from your hard drive (see Figure 4).

Figure 4. Selecting an image file.

The Upload button becomes visible and the TextInput of the ImageUpload component displays the filename. Click the Upload button and notice the ProgressBar becomes visible and displays the upload status; when the upload completes, you’ll see the photo displayed for the employee (see Figure 5).

Figure 5. Successfully uploading the image file.

The employee photo is uploaded and the server response displays in the Form control above the DataGrid. Check the upload directory on the server to ensure the file has arrived successfully. And with that, you’re done!

Troubleshooting

A simple HTML page can help troubleshoot your Java servlet to ensure it’s working correctly. Create a page named upload.html in the root of your Java app and place this code in it:

For Internet Explorer, you will have to choose View > Source or Page > View Source to see the full XML response. Otherwise, it will only display text like the following:

File successfully written to server at 04.30.09 02:46:31 PM

Where to go from here

This article showed you how to upload files with Flex and Java. Using the powerful RIA framework provided by Flex, you can send a file to the server with additional parameters and receive and process the server feedback. Flex makes it easy to add custom components and events. This customization provides greater flexibility for your app to meet your design requirements; instead of being limited to the components that ship with Flex, you can let your imagination and needs take you to new levels of ingenuity.

How can you modify this app to meet your business needs? Here are some ideas:

Add database code to your Java servlet so you can read the employee data. This app uses some static XML to simplify the code demonstrations, but a database can open up a whole new world of dynamic capabilities for you.

Write the employee’s image filename to the database in the Java code. Modify the servlet to read the employee information from the database and render it as XML for your Flex application. Then, when you load the Flex page, it will display the current images for the employees.

Use a URLLoader to emulate an upload of a file created entirely in memory. URLLoader encodes the image in memory (in the Flash Player), which you can then upload to the server. For example, you can use this method to add a watermark to the photo.

Add a button to display only those employees without photos. You can send a parameter to the servlet to indicate what data you need.

Build search functionality for the app. Send the search parameters from Flex to the servlet and receive a more dynamic set of data.

Implement an authentication and authorization mechanism to allow only administrators to upload images. For example, you can implement the Java Authentication and Authorization Service to provide security.

Add a version of this app to your organization’s intranet. Your boss will be wondering why this wasn’t done before!