Tuesday, March 21, 2006

AJAX Struts File Upload Progress Meter

** This Post is a work in progress, and is still being worked on, it hasn't been edited yet, and may contain errors, use at your own risk **

Over the course of the last year or so I have been hearing a lot about AJAX, and how cool it is, and what neat stuff you can do with it. At first I wasn't too impressed, mostly because I have heard it all before. It wasn't until I saw
google maps that I realized how cool it was. I have been itching to use Ajax ever since.

My first attempt at AJAX was using the Google Maps API to add a map to the search results page on CampRate.com. It is fairly simple, the search allows the visitor to search for campgrounds given a zip code and a search radius. I search the CampRate.com database and return the campgrounds in the area, and I then add Site Markers onto the google map so that it is easier to see where the campgrounds are located. This was fairly easy to setup given the fact that Google opened up their API.

Once I finished the Google Map hack, I was looking for something else to do. After looking around for a little while I thought of the perfect thing to AJAXify. On CampRate.com we allow Campground Owners to upload images of their campgrounds to the site, and campers are also allowed to upload images of their camping trips for everyone to see. The interface for this is very simple, it is just a regular File browse box and a submit button, once they upload the image, the browse box goes away and a thumbnail of the image is inserted. This is a very basic and a very late 90's way of doing things. What a prefect thing to AJAXify.

Once I knew what I was going to work on, I needed to figure out how I could improve on the design. After a couple of revisions I came up with the new design and layout. One of the features that I thought would be good to use AJAX for, is a progress bar for showing the status of the upload.

Here is what the new upload page looks like, this is where I would like to add a progress bar.

Progress Bar.
Before I started coding for the progress bar, I decided to search around to see if anyone else had used a progress bar before. I found a bunch of examples, PHP, Ruby, and a good one using Java + DWR. I decided to look at the Java + DWR example since I was already using Java and DWR on CampRate.com. The Java + DWR example was a great start, the only problem was that it didn't use Struts and once the file was uploaded it changed pages. There were some comments associated with the article that mentioned how to get it to work with Struts, so I decided to take the source code from the article and play with it and see if I could get it to work with Struts.

What I wanted to change in the example.
  • Get the example to work with struts
  • get the file to upload to a selected directory
  • show the status of the file in the progress meter
  • when the file is uploaded don't leave the page, stay on the same page (no redirect or refresh).
What I did.
  • I downloaded the war file with source code from the article
  • refactored the project directory
  • changed the build script
  • setup struts, log4j
  • added logging statements for easier debugging
All of the new struts code that I added was put into a new package net.kencochrane so that you can easily see what is was originally there, and what was added in order to get struts to work with the original Code.

Struts Changes
  • Added the struts libs to the lib dir in the project
  • added the XML files to the config directory
  • changed web.xml so that it works with struts
  • created some actions, and form

Code Changes
  • Added a MultipartRequestHandler
  • added struts actions to handle all requests.
  • The example now actually stores the uploaded files to a temp directory.
  • Added a new package net.kencochrane

Uploading a file without leaving the page
I looked around to find a way to upload the files without leaving the page, but from what I could find, I guess you can't do this with javascript because of security reasons. The most common way to do this was to use an iFrame and use this iFrame to hold the upload form, and when the form is submitted the form gets posted like normal, and using some tricks with javascript you can make it look like the file is uploaded without ever leaving the page.

I changed the index.jsp file to include an iFrame, the iFrame holds the upload form. Using javascript I was able to make it looks like the files are being uploaded without leaving the page.

Here is what the new pages look like, the first image looks like the original form, the only difference is that the page is now using an iFrame to hold the upload form.

File upload in progress, it displays the progress bar until it is complete, and then the bar goes away and is replaced with a status message.

The file is finished,
progress bar is hidden, and the status message tells you the file status.

What is left to do
  • add better error checking
  • Check for file being uploaded that is too large.

Now What
Now that I have the example working the way I want it (with struts, DWR, and having the file uploaded without leaving the page.) I can work on adding this code to CampRate.com.

The more that I think about it, I could also use this on PopcornMonsters.com as well, we allow people to add images for movies, and actors to the site, but the interface is very ugly, once I get the code written for CampRate.com I could easily spend the time and get the same code to work on PopcornMonsters.com, that would make the whole adding images experience so much better.

Special Thanks to Pierre-Alexandre Losson for writing the original Article and for posting his code for everyone to use.

Download the code from this post for AJAX Struts File Upload Progress Meter.

I will update this post with some completed pictures once I finish up with all of the code. Feel free to post comments.

Ken Cochrane