File Upload Using Flex/Central/Java
Inspired by Matt Chotin's recent guest post, I decided to take a moment to document file upload using a Flex application deployed in Central leveraging a Java application server. The biggest challenge is that there's a lot of moving parts, but the implementation is actually quite easy. Let's take a look at the Java servlet, the Flex application and the Central hooks. And as always, at the end there's a Captivate demo, of course!
The servlet, all nineteen lines of it, is pretty straightforward. I didn't account for anything more than a single file upload, and my error management is atrocious, but this sets the groundwork. If there's something that's not covered that you have questions about or would like to see the code for, just drop me an email and I'll see what I can do to update the example.
I've been a fan of the multipart request library at Servlets.com since it was published and I use it here again. Why? When Central makes a file upload it does so through HTTP POST, very much like a file upload done through classic HTML. At the server we need to grab that binary stream and save it to disk. Rather than think about all the HTTP details and reinvent the wheel, this little (but exceptionally robust) library does the trick.
import com.oreilly.servlet.MultipartRequest;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
public class UploadServlet extends HttpServlet {
protected void doGet( HttpServletRequest req, HttpServletResponse res ) throws ServletException, IOException {;}
protected void doPost( HttpServletRequest req, HttpServletResponse res ) throws ServletException, IOException {
MultipartRequest parts = new MultipartRequest( req, "C:\\MyUploadPath" );
PrintWriter out = res.getWriter();
out.print( "SUCCESS" );
out.close();
}
}
While the combo of Flex and Central and all the great file IO capabilities (and more) lead to an obviously huge amount of potential, my whiz-bang UI will consist of a Button and an Image. The Button will eventually trigger the file dialog and get the file upload going. Once the file upload is complete, the Image's source property is set to the location of that file on the server. The Image subsequently loads the file and displays it in the body of the application.
For the purposes of this demonstration I have set the Image control up to scale its contents and display them horizontally centered.
You'll notice that on the Button control I capture the click event and call the doUpload() method in the application. This method creates a Central FileReference object, and prompts the user to select a file. In this case, I've limited the file types to JPEG images. Before I start the upload I attach the application itself (probably not a best practice long term) as the listener for any problems that might arise during the file transfer.
The two methods that the application listens for are onUploadSuccess() and onUploadFailed(). There are a variety of other events that can be triggered, but for the purposes of getting a file to the server, and making sure it happened successfully, this will work just fine. Once the user selects a file, the upload process begins with a call to FileReference.upload() and specifying where in the world our upload servlet lives.
If the file has been transferred successfully then the onUploadSuccess() method will be called. The onUploadSuccess() method gets a couple arguments; a reference to the file that was uploaded and any textual response from the server. I could have been inventive and accounted for existing files of the same name, populating the image in a database, etc. at the server and returned a string as to where I can access that file. This would have shown up as the response argument. Instead, I'm lazy, and I use the file reference to get the name of the file and a static URL.
The onUploadFailed() method I've implemented is equally lazy - I simply alert the user to an error by telling them what the server tells me. Realistically, I might chose to pull the local file into Central's cache and work with it there, or behave as though I am working offline and store a reference to the file for access when the network has been restored. Once again the options are limitless.
private function doUpload( event:Object ):Void {
var file:FileReference = new FileReference();
// Ask the user to choose a file to upload
if( file.browse( ["JPEG Files", "*.jpg"] ) ) {
file.addListener( this );
file.upload( "http://myurl/servlet/MyUploadServlet" );
}
}
private function onUploadSuccess( ref:FileReference, response:String ):Void {
imgUpload.source = "http://myurl/myfilepath/" + ref.name;
}
private function onUploadFailed( ref:FileReference, error:String, response:String ):Void {
mx.controls.Alert.show( "Upload error: " + error );
}
That's all she wrote. Deploy that application and add native file upload to your bag o' tricks today!
Posted by khoyt at 03:45 PM | Comments (2)
December 11, 2004
Central/Flex Hex Editor
This one is from the category of "Just Because I Could" - a Hex Editor, written in Flex and deployed in Central (to allow for file IO). An editor of this nature can potentially represent a ton of data. The image file shown here weighs in at about 433 KB; it results in around 27,000 rows of hex data! Despite the obvious overhead, I'm eager to continue to add a few features as I have some future uses for portions of this application.
Since I'm not exactly sure just how useful this would be out there in the public domain (there's already a plethora of hex editors out there), I'm not releasing the code. If you're still interested in the source you can email me and we?ll talk.
Posted by khoyt at 06:36 PM | Comments (0)
December 06, 2004
File Explorer in Flex
Okay, this one's coming at you straight from the customer request files! Last week I had a customer ask for an example showing Tree control manipulation based off RemoteObject calls. The customer asked for an example where node data would be appended dynamically as data was returned. They were displaying hierarchical data specific to their business, so I went for the next best thing - system file data.
It turned out to be easy enough to emulate file system structure in a Tree control based off service call results, so I couldn't just stop there. I figured that I'd keep going and provide additional display metaphors. Windows Explorer displays additional file data in a grid, and upon deconstructing its behavior, reflects navigation in the tree in a somewhat complex fashion as well. The example is available for your convenience.
I implemented a simple Java object as the service, and that provides me with some convenience methods for accessing the data in the form I want/need. I'd likely refactor that code somewhat, so don't use it as a pure reference of what should be done on the server-side (outside of the pattern of providing a service adapter). I've also roughed in the MXML for direct file access through an address bar. I haven't hooked it up, but the code is there for you to expand upon if you so please.
My favorite part of the application is the formatting, totaling, and summation that take place at various points. In the following Captivate demonstration for example, you'll notice that right out of the gate there's a total for the number of objects, and their combined size (in GB) in the status bar. As the Tree is navigated, those values will change - and they're even intelligent about the units in which they display (not always GB). Formatting also takes place in the DataGrid through labelFunction properties on the DataGridColumns.
Posted by khoyt at 05:13 PM | Comments (3)
December 02, 2004
Clock Component in Flex
I've seen the occasional request for a clock component in Flex, and I'm wondering what some of the requirements might be. Are we talking an analog clock or more along the lines of a text field approach? The Windows system clock shows both in a fairly simple fashion - is this adequate? Just the analog clock? Just the masked text field? Since there are numerous analog clocks done in Flash throughout the community, I suspect the requirement is for the later of the two. If you have a need or interest in seeing a component of this nature, let me know by posting in the comments with your particular requirements. The more specific the better.
Posted by khoyt at 04:58 PM | Comments (2)
OS X Style Dialog Using Macromedia Flex
I recently found myself entranced with way OS X dialog boxes appear and disappear out of the top of the window to which they belong. Becoming fixed on the UI, as is often the case, I found myself compelled to see if I could duplicate the effect using Macromedia Flex. The basics didn't turn out to be that hard.
I've made my initial pass available for review and expansion. There are a few shortcomings I'd like to address, but as the year draws to a close, so do the number of spare hours I have in a day (smile).
Update [Dec 3, 2004] : The original example SWF file was built using the Developer Edition of Flex and as such was going to timeout after 48 hours. I've replaced the actual application SWF with a demonstration SWF created using Captivate.
* Future improvements might be: Use the Text control instead of Label which limits me to one line of text
* Externalize the icon as a property, and make a small default set available
* Allow for button definition along the lines of the Alert control
* Remove focus from the main UI in favor of a default button on the dialog

