Friday, July 6, 2012

Tapestry Ajax Upload Fixin

Do you have problems with file uploading when using it with ajax requests?
The issue is that ajax file uploading isn't transparently supported. There are some approaches to solve this issue. I will use jQuery as client side framework and Tapestry5 as server side for all examples.

1. Using advantages of html5 http://www.w3.org/TR/XMLHttpRequest2/#interface-formdata

The main idea is to use special JS interface called FormData. We can create it from existing form element and it will copy all data from it or we can create empty FormData and fill it from scratch. Then we can use it in ajax request and it will work.

... in almost all modern browsers: Chrome 7+, FF 4.0, IE 10+(really?), Opera 12+, Safari 5+. But what about old browsers?

2. Using usual form submission in iframe.
The idea is to emulate asynchronous request via form submission in separate iframe. We just need to create iframe and form targeted to this iframe, attach file inputs to newly created form, copy input values from original form to new as hidden fields, and submit this form as usual. Response from server will be automatically loaded in iframe body.


In this case we should also improve server logic to think about such request as ajax request. And don't forget about escaping.

3. Using both approaches
The issue is only to to detect if html5 FormData feature is supported by browser. If so use html5 way, no - use iframe. This is simple as a boot.


So, jquery plugin can look like this one:


Now lets see how to integrate all this with Tapestry. The best way is to fix existing upload component. And it is possible thanks to mixins, or in our situation we can call it fixin :)
Lets create fixin with possibility to be attached to forms. It will attach JS handler that will use jquery upload plugin to submit form and then update tapestry zone with server response.


We should also improve server-side processing logic for upload requests in iframe. They should be interpretted as xhr requests to be able to render partial ajax markup and be of type text/plain to prevent escaping.


Usage:


You can try it here (live demo)
Sources (github)

No comments:

Post a Comment