Skip navigation

In RichFaces 4.5 we've upgraded the rich:fileUpload component to take advantage of new APIs both on client and server side.

 

These changes are mostly in the background. The two visible changes are differently styled progress bars (based on Bootstrap) and the ability to drag and drop files onto the component. However the new APIs really simplified the somewhat difficult task of submitting and processing the files and are worth a few lines:

 

File API

A new API comes to browsers with HTML5, allowing access to the files provided by the user

input.val();
// "C:\fakepath\chart1.png"



The "C:\fakepath" is obfuscation by the browser, this is the only valuable information we can retrieve from an <input type="file" />, but with File API we can do better

 

input.prop("files")[0];
/* File: {
    lastModifiedDate: Mon Sep 29 2014 13:35:47 GMT+0200 (CEST)
    name: "chart1.png"
    size: 14679
    type: "image/png"
} */

 

Drag and Drop

With the File API and drag and drop support we can also retrieve files from a dropEvent (event.dataTransfer.files). The dropEvent can be intercepted on any element so it is possible to implement a file upload without the use of a file input.

 

XmlHttpRequest Level 2

The second important change in HTML5 is the FormData interface that let's us create a form-like object to be sent by an AJAX request. In this case we can append the files we retrieved previously to that object. Without access to any kind of File representation, the way to get the file to the server was to submit the form, loading the result into an <iframe> and intercepting the AJAX response to apply the changes to the main page.

 

var formData = new FormData(form);

formData.append(fileUpload.id, file); // key-value mapping
this.xhr = new XMLHttpRequest();
this.xhr.open('POST', url, true);

/*
  xhr handlers
   …
*/
this.xhr.send(formData);







there are several other things that have to be taken care of with regards to JSF but those are above the scope of this post.

 

XHR also allows us to handle the progress of the file upload on the client side. Previously we had to handle it on the server, inserting rich:progressBar into the element during rerender and connecting it to a request parser through a JSON resource.

this.xhr.upload.onprogress = function(e) {
    if (e.lengthComputable) {
        var progress = Math.floor((e.loaded / e.total) * 100);
        /*
          update the progressbar 
          …
        */
    }
};







 

NOTE: these APIs and thus the fileUpload component are not supported by older browsers, most notably IE9

 

Servlet 3.0

On the server side the big change was the implementation Servlet 3.0, making it easier to process the incoming request.

 

Collection<Part> parts = request.getParts();

for (Part part : parts) {
    // one of the parts will be the file we appended to formData
    String contentDisposition = part.getHeader("Content-Disposition");
    // form-data; name="form:upload"; filename="chart1.png"
    String filename = MultipartRequestParser.parseFileName(contentDisposition);
    if (filename != null) {
        files.add(new UploadedFile30(part.getName(), filename, part));
        // the file is then retrieved through part.getInputStream()
    }
}



We still support Servlet 2.5 which doesn't provide access to the parts, in that case the entire request has to be parsed piece by piece.

 

Links

Filter Blog

By date:
By tag: