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!
NOTE: This article was originally written in December of 2004 and is sorely outdated. The examples used are constructed on a version of Flex that’s now two versions (three years) old. Macromedia Central no longer exists, though you’ll find all of that functionality and more in Adobe AIR. I’ve rewritten this post using more recent libraries, and to be far more descriptive. Please visit the latest write-up.
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.
<mx:Application initialize=”initApp( event )” xmlns:mx=”http://www.macromedia.com/2003/mxml”>
<mx:Button id=”btnUpload” label=”Upload…” click=”doUpload( event )” />
<mx:Image id=”imgUpload” width=”100%” height=”100%” horizontalAlign=”center” />
</mx:Application>
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!
December 21st, 2004 at 3:32 pm
Two questions: Is there a cost to deploying a central application for central licensing (other than the flex licensing). Secondly, is it likely that the flash player will ever allow file uploading (with the security constraints that the web browser emposes), or is Central going to be the cleanest way to go. The timeline I am speaking of is 6-9 months.
December 21st, 2004 at 3:43 pm
Ken,
Generally speaking, no there’s no additional cost to deploying a Central application with Flex (other than Flex). To be sure though, I suggest you check the licensing options on MM.com.
As for file upload being a part of the Flash Player, rest assured that we are aware of the demand, but we cannot commit to features or timeframes for future products. Central is going to be your best choice for applications requiring file manipulation.