Wicket in Action

Uploading files to Wicket IResource

14 November 2012, by martin-g

Several times people have asked in the mailing lists how to integrate JavaScript widgets for file uploading like Plupload, Uploadify, Fine Uploader or jQuery-File-Upload with Apache Wicket.

The problem

Wicket provides FileUploadField which can be used as part of a form submission. It supports HTML5 multiple attribute and works great but these JavaScript widgets are smarter than that!

The widgets provide functionalities to select the files to upload with HTML5's Drag & Drop, or if HTML5 is not supported by the browser then fallback to Flash or IFrame solution.

So the widgets don't really need a form to be able to do their work. All they need is a destination URL to send the bytes to.

The solution

Users of Apache Wicket know very well its WebPage component. It is used as a main container of other smaller components that construct the content that is delivered to the client when a given url is requested.
Since file uploading doesn't really need to construct a page and its optional response often is just a piece of data explaining that the upload is successful or not we are going to use Wicket's IResource as an endpoint. IResource could be mounted at a predefined mount path just like pages by using a ResourceReference:

MyApplication.java:

@Override
public void init() {
    super.init();

    mountResource("fileUpload", new FileUploadResourceReference(BASE_FOLDER));
    mountResource("fileManager", new FileManageResourceReference(BASE_FOLDER));
}

Here we mounted two resources - one as destination for the file uploads and another for managing the uploaded files (it can serve and delete them).

Check Wicket 1.5 - Mounting resources for more information.

Reading the uploaded files

The main problem to solve is how to read the uploaded files from the request parameters.
Actually the solution is quite simple, just few lines of code:

AbstractFileUploadResource.java

@Override
protected ResourceResponse newResourceResponse(Attributes attributes)
{
    ServletWebRequest webRequest = (ServletWebRequest) attributes.getRequest();
    MultipartServletWebRequest multiPartRequest = webRequest.newMultipartWebRequest(getMaxSize(), "ignored");
    // Note: since Wicket 6.18.0 you will need to call "multiPartRequest.parseFileParts();" additionally here
    Map<String, List<FileItem>> files = multiPartRequest.getFiles();
    ...
}

We just asked Wicket to create a WebRequest that knows how to read the multipart request parameters. The final result is a map with keys the name of the request parameter and values the respective FileItems which can be used to get the uploaded file's name, size, input stream, etc.

And basically that's it!
From here on our code is responsible to store somewhere these files and return a response to the client is the format it expects - JSON, HTML, ...

Demo

At my GitHub account you may find a demo application that integrates jQuery-File-Upload. I've chosen this widget because it looks very nice and I wanted to contribute it to Wicket Bootstrap project. It appeared that the docs and APIs of this widget are not the best one could wish for. To be able to duplicate the functionalities from its demo page I had to read and debug its internals (specifically jquery.fileupload-ui.js).

There are still some functionalities which do not work completely:

  • the cancel button
  • the gallery preview of the uploaded files
  • the UI is broken in IE (I blame my CSS skills for that!)
  • ...

But all these are not directly related to the topic of this post - how to upload files to Wicket IResource and how to read them at the server side.
If you need this component for your application and you fix this issues I'll gladly accept your Pull Requests.

-->