Simple Struts 2 file upload example

 

Developers often face a complex process when it comes to file transfers from a web browser to a remote application server. Fortunately, most enterprise web frameworks provide file upload facilities that simplify the task.

In this Struts 2 file upload example, we’ll walk through the steps of how the popular Apache Java web framework makes it possible for a remote client to transfer a local file through their browser and save it in a folder on the remote application server.

Struts 2 file upload steps

A developer can create a Struts 2 file upload application by following these five steps:

  1. Add the required commons-fileupload and commons-io dependencies to a Java web project;
  2. Create a JSP that uses the Apache Struts form and file custom tags;
  3. Code a Struts action class with setters that map to the name of the file, as specified s:file tag of the form;
  4. In the execute method of the Struts action class, use standard Java IO packages to save the uploaded file; and
  5. Create a success JSP that informs the user the file was uploaded successfully.

The JSP that contains the special Struts tag that creates an HTML form element is the key to the Apache framework’s file upload capabilities. A prototypical Struts upload form looks like this:

More File Upload Options

I put together a bunch of file upload tutorials. Pick your technology and get uploading!

Uploading files to the server need not be a problem.

<%@ taglib prefix="s" uri="/struts-tags"%>
<%@ page contentType="text/html; charset=UTF-8"%>
<html>
<body>

  <s:form 
    action="fileupload" 
    method="post" 
    enctype="multipart/form-data">

      <s:file name="uploadedFile" label="File" />
      <s:submit />

  </s:form>

</body>
</html>

The method of type post and the enctype of mutlipart/form-data will remain the same from one Struts file upload form to the next. The action attribute must map to the mapped name of the Struts action class that handles the request on the server, and the file name must map to a property declared in that action class.

After the attribute is properly map, the next step is to code the corresponding action class.

The Struts 2 file upload action class

The name of the file in the Struts upload form above is uploadedFile. As a result, the action class that supports this form must have a setter method named setUploadedFile that takes a java.io.File object as an argument, and it must also have a setter method named setUploadedFileFileName that takes a String as an argument. The Struts framework will pass the uploaded file and its name to these methods, but developers should pay careful attention to the fact that the properties declared in the action don’t have to map exactly to the setter names.

package com.mcnz.struts;

import java.io.*;
import java.util.*;
import java.util.stream.*;
import org.apache.commons.io.*;
import org.apache.struts2.convention.annotation.*;

import com.opensymphony.xwork2.ActionSupport;

@Action("/fileupload")
@Result(name = "success", location = "/results.jsp")
public class FileUploadAction extends ActionSupport {

  private File uploadedFile;
  private String uploadedFileName;
  private String localDirectory = "C:\\temp";

  public void setUploadedFile(File file) {
    uploadedFile = file;
  }

  public void setUploadedFileFileName(String name) {
    uploadedFileName = name;
  }

  public String execute() throws Exception {
    File localFile = new File(localDirectory, uploadedFileName);
    FileUtils.copyFile(uploadedFile, localFile);
    return SUCCESS;
  }

  /* Used to obtain a file listing for JSP display. */
  public Set<String> getFileList() {
    return Stream.of(new File(localDirectory).listFiles())
      .filter(file -> !file.isDirectory())
      .map(File::getName)
      .collect(Collectors.toSet());
  }

}

In the above action class, the execute method takes the uploaded file and saves it to the C:\temp folder.

A helper method named getFileList() isn’t necessary, but I added it to allow the results page to list all the files that currently reside in the upload folder.

Struts 2 file upload confirmation page

The target of the action’s successful invocation is the results.jsp. Developers don’t need to make this page overly complex. By the time this page is invoked for rendering, the file will have already successfully uploaded. Here’s a simple results.jsp to satisfy the current use case:

<%@ taglib prefix="s" uri="/struts-tags"%>
<%@ page contentType="text/html; charset=UTF-8"%>

<html>
<body>
<p> <s:property value="uploadedFileName"/> was uploaded successfully. </p>

</body>
</html>

Enhanced results page

If a user was to upload a file named image.jpg, the above results.jsp would simply print out “image.jpg was uploaded successfully.

If a developers wants to enhance the output, they would add a getFileList() method to the action class. By including this method in the results.jsp along with the original file upload form it create a reasonably enhanced and appealing form for the user to see. Although the process is significantly more complicated, I feel that it’s worth it:

<%@ taglib prefix="s" uri="/struts-tags"%>
<%@ page contentType="text/html; charset=UTF-8"%>
<html>
<body>

  <s:form action="fileupload" method="post" enctype="multipart/form-data">
    <s:file name="uploadedFile" label="File"/>
    <s:submit/>
  </s:form>

  <s:if test="%{uploadedFileName!=null}">
    <p><s:property value="uploadedFileName"/> was uploaded successfully.</p>
  </s:if>

  <h2>Directory listing</h2>

  <s:if test="%{fileList().isEmpty()}">
    <h2>No files in the directory</h2>
  </s:if>
  <s:else>
    <ul>
      <s:iterator value="fileList">
        <li><s:property /></li>
      </s:iterator>
    </ul>
  </s:else>

</body>
</html>

File upload Maven dependencies

Along with the standards Struts libraries, the file upload utility also requires commons-io and commons-fileupload facilities. Developers will need to add the following Maven dependencies to your application to get the Struts 2 file upload facilities to work:

<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.2.1</version>
</dependency>
<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>1.3.2</version>
</dependency>

After a developer adds these dependencies to the project, and they have Java installed, they can run the Struts 2 file upload application and watch the temp directory get populated with resources every time a user clicks the file upload button.