35. Implementing File Upload for Spring Web Flow

PROBLEM

In the event that an application is implemented using Spring Web Flow, there needs be a way to implement file uploads that doesn't resort to using Spring MVC.

SOLUTION

The HTML FORM and INPUT elements are used to implement the user interface for uploading files. In an HTML form the ENCTYPE determines how the form data is encoded, and for uploading files the value "multipart/form-data" should be used. For the INPUT element the type should be set to "file".

With the user interface addressed by HTML, the next component to address is the backend logic. The Spring Web Flow application needs to be setup to handle the multipart data that is being sent from the UI. Spring supports this with a MultiPartResolver, and Skyway Builder projects are automatically bootstrapped to with the MultiPartResolver configured.

HOW IT WORKS

As mentioned earlier the first step is to implement the user interface for uploading content, and the following list describe the details.

Implementing the file upload user interface

  1. Update the ENCTYPE of the form to "multipart/form-data". This can be done in a form implemented using the standard HTML FORM tag, the Spring Form tag, or the Skyway Form tag. [REQUIRED]

  2. Add an HTML INPUT element with the TYPE attribute set to "file", and set the NAME attribute to the variable where the uploaded file should be stored. [REQUIRED]

This following JSP fragment shows a typical file upload implementation using using the Spring Form tag and standard HTML elements.

Example 2.40. File Upload - HTML

<form:form modelAttribute="photo"1 enctype="multipart/form-data"2 >
    <input id="multipartFileUpload" name="multipartFileUpload" type="file" value="" />3
    <input name="_eventId_save" type="submit" id="save" value="Save" align="right">
    <input type="submit" id="cancel" name="_eventId_cancel" value="Cancel">
</form:form>

1

The ModelAttribute is set to "photo". While you may ultimately want to store the file (and it's related attributes) in this variable, this won't occur automatically. On the server you will need to individually set the variable attributes using the file data from the "multipartFileUpload" request parameter.

2

The encoding type is set to "multipart/form-data"

3

This input html element will let the end-user select a file from their filesystem to upload. The file is bound to a request parameter called "multipartFileUpload".

Skyway Builder already bootstraps the Spring Web Flow application to support file uploads, so there is zero configuration required by the developer. The following list describes the relevant configurations that are automatically bootstrapped by Skyway Builder.

Bootstrapping of File Upload Support

  1. A multiPartResolver is registered. See the generated web context file (projectName-generated-web-context.xml).

Below is the snippet from the Spring Web Flow XML document. This snippet sets up the flow and processes the save request.

Example 2.41. Spring Web Flow Configuration

<view-state id="EditImage" model="photo"1>
    <transition on="save" to="ListImages">
      <evaluate expression="ImageService.saveImage(photo, requestParameters.multipartFileUpload)"2 
                result="" result-type=""/>
    </transition>
    <transition on="cancel" to="ListImages"/>
  </view-state>

1

The model variable for the view state is set to photo.

2

The evaluate expression is passing the photo variable and multipartFileUpload request parameter to a service.

The only responsibility of the developer is to implement the service operation (i.e. ImageService.saveImage()) that accepts both the domain object (photo) and multipartFileUpload (org.springframework.web.multipart.MultipartFile) as input parameters. In the implementation of operation you can extract set the domain object with the individual properties from the file (MultipartFile).

Example 2.42. Accessing MultipartFile

photo.setContent(multipartFile.getBytes());
photo.setContentSize(new Long(multipartFile.getSize()).intValue());
photo.setContentType(multipartFile.getContentType());
photo.setFilename(multipartFile.getOriginalFilename());

RELATED RECIPES

  1. Implementing File Upload for Spring MVC

  2. Streaming binary content