Friday, September 11, 2009

Upload file in SmartGWT

Upload a file to a server from your browser is not a big deal. But how to do it, if you have:
  • SmartGWT (a Google Web Toolkit with a SmartClient library)
  • It is LGPL, so no proprietary extension on a place
  • You don't want to use ExtGWT just only for one single upload function and thus risk your project won't really work on older browsers that are still might be in use.
  • You want it nicely done at background with a clean callback, of course. :-)
Here how you do it:
  1. In com.smartgwt.client.widgets.form.DynamicForm, set it to multipart by passing it Encoding.MULTIPART.
  2. Create an internal iframe, using com.google.gwt.user.client.ui.NamedFrame and call it, let's say "foo" (sure no better name came into my head now, LOL). Make it 1x1 pixel width and set visibility to false. It is not actually a thing user needs to see.
  3. Now use setTarget("foo") method to let your DynamicForm use that it as a target.
  4. Also use setAction(url-to-your-processing-servlet) to let DynamicForm actually send stuff there. You can do it like ("upload" — is your servlet accessible):
    .setAction(GWT.getModuleBaseURL() + "/upload");
  5. Now, add mouse click handler to your IButton and use submitForm() method out of DynamicForm instance object. It will send the form and that iframe we created earlier will receive a result. This way we achieve upload in background.
  6. Add a native JavaScript method, that will be seen normally in the loaded page, so parent windows can simply call it. That's exactly what do we need, when upload has been finished. More how to add JavaScript native methods, refer to GWT documentation about JSNI.
Now, time to write our Servlet for file upload. Great Java that comes with power station to your computer, yet has zero API to process multipart forms. This is just frustrating. But here is a cure: Apache File Upload library. Read the API how to use it. But generally, you simply iterate over fields and once you've got a filename out of the stream, you have the file. In this way you can send lots of files at once.

Your servlet should call back our method, we've defined in step #6. You simply set content type to text/html, write some simple html and a JavaScript that would call parent on window load — this way your iframe will call your client back. You may pass anything you want and respond anything. In my case it just closes upload dialog and says job done.

That's it. Implementation is up to you — use imagination... :-)

3 comments:

nbawww said...

Hello, nice job.
That's exactly what I want to do, but i can't send the response from servlet to the client. Could you please give more details about this step? and it will be very helpful and great if you can post your source code.
Thanks.

Nicolas said...

Thank you for your job !! But can you post some code !!

Thank in advance !!
Nico

hardikm said...

Hello,

Thank you.. Nice steps....
It helped a lot. :)