Ioannis Deligiannis Ioannis Deligiannis - 7 months ago 86
Javascript Question

How can I add a client-side progress listener to a JSF 2.2 ajax request?

I am trying to add a client side progress bar to

JSF2.2 ajax
requests. What I would ideally like to do is get the request header size and receive updates for the status of the
POST.


I do not know a lot about
JS/JQuery
but as far as I can tell,
JQuery
must initiate the request in order to achieve this(see here)

Is there a way to do this from the client-side only?

If this is not possible, what other (native) options do I have?

Thanks,

PS1. Although the main scope for this, is a file upload progress bar, I would like to be able to apply on the full request size.
PS2. I know there are a few libraries that offers this for free, but ATM I don't wan't to use any.

Answer

After some research this is a little more complicated than it first appears.

JSF and multiple files

First of all, JSF 2.2 defines <h:inputFile> tag which is limited to a single file, i.e. it does not support HTML5 parameter multiple=true. See this for more details. On the other hand, it is very easy to extend this tag to allow multiple files since the uploaded files are fetched from the request, so they are easily available.

Where are the files parsed and persisted?

All JSF requests are handled by the FacesServlet, which is annotated with Servlet's 3.1 tag @MultipartConfig. This annotation basically does all the heavy lifting of extracting and writing the uploaded files. See this and this.

Although this is very handy and takes care of most things, it doesn't have a progress listener interface, which means that you will get the files (Parts) when they are fully uploaded. I don't see a way to actually intercept this is a clean way in order to implement a server-side progress bar.

Server-side Vs Client-side progress listener

In order to implement a server side progress listener, you will need somehow to handle files yourself and notify the user about the progress using polling or WebSockets.

For the client-side, you will need to either write a custom POST function like this or use a library like this this to handle the POST as most browsers don't provide progress information. Basically, instead of using the browsers functionality to do a post (AFAIK) you handle the request yourself and hence you have control of the bytes transferred. The problem here is that FacesServlet expects a request which is formatted by the jsf.js functions and I do not see an easy way to intercept the JS request just for processing file upload.

What are my options then?

I would safely suggest using an existing library that offers this functionality. If you have the time and still want to DIY, I think that the best way to go is to write your own FileUploadServlet that 'understands' JSON or XHR and use a JQuery plugin to initiate the upload and provide the client-side progress bar.

Example

I have finally decided to go with JQuery/blueimp fileupload. See this comment for details. Note, that this is not actually part of the normal JSF Flow, I developed a custom way for feeding the actual parts in my application.

PS. As I am new to this, don't read this answer as a definitive answer but as a starting point for your own research.

Comments