http://www.developer.com/java/web/5-java-upload-applets-for-your-web-applications.html

Back to article

5 Java Upload Applets for Your Web Applications


April 25, 2012

In this article, I profile five upload solutions for Java Web applications:

  • YUI Uploader
  • GWTUpload
  • Postlet Applet
  • JUpload Applet
  • PrimeFaces Upload

The article will not help you decide which one to choose; it just presents the features of the five solutions for Java developers.

For additional reading on Java upload solutions, see my two previously published JavaBoutique articles on COS and SWFUpload and "FileUpload."

YUI Uploader

The YUI Uploader is a great upload component from Yahoo. This customizable component has a great design that can accomplish everything from simple uploads to complex ones.

YUI Uploader Capabilities

Specifically, the YUI Uploader allows for these features (taken from YUI Uploader site):

  • Multiple file selection in a single "Open File" dialog.
  • File extension filters to facilitate the user's selection.
  • Progress tracking for file uploads.
  • A range of available file metadata: filename, size, date created, date modified, and author.
  • A set of events dispatched on various aspects of the file upload process: file selection, upload progress, upload completion, etc.
  • Inclusion of additional data in the file upload POST request.
  • Faster file upload on broadband connections due to the modified SEND buffer size.
  • Same-page server response upon completion of the file upload.

Implementing YUI Uploader

In this section, you will see how to implement the YUI Uploader into a Web application built in a Java context. To start, you must download the YUI Uploader. Depending on the Web application context, to use the Uploader Control, include the following source files in your Web page (in this example I stored the YUI Uploader into a folder named /yui under application root):


<script type="text/javascript" src="yui/build/yahoo-dom-event/yahoo-dom-event.js"></script>
<script type="text/javascript" src="yui/build/element/element-min.js"></script>
<script type="text/javascript" src="yui/build/uploader/uploader-min.js"></script>

Next, you can place the code necessary to configure the YUI Uploader. First, you can see a few details about each representative chunk of code, and after that you will see the code.

First of all, you need to specify the path (relative to the page or absolute) of the uploader.swf file to the location of the HTML page in which a Uploader Control instance will appear and then render the uploader as a button.


// Instantiate the uploader and write it to its placeholder div.
YAHOO.widget.Uploader.SWFURL = "yui/resources/uploader.swf";
var uploader = new YAHOO.widget.Uploader( "uploaderUI",
                                             "yui/resources/selectFileButton.png");

The Uploader has a number of methods that allow you to manage the upload process and dispatch various events for different aspects of the upload process. To add event listeners to various events called by the uploader you may do something like this:


// Add event listeners to various events on the uploader.
// Methods on the uploader should only be called once the contentReady event has 
// fired.
uploader.addListener('contentReady', handleContentReady);
uploader.addListener('fileSelect',onFileSelect)
uploader.addListener('uploadStart',onUploadStart);
uploader.addListener('uploadProgress',onUploadProgress);
uploader.addListener('uploadCancel',onUploadCancel);
uploader.addListener('uploadComplete',onUploadComplete);
uploader.addListener('uploadCompleteData',onUploadResponse);
uploader.addListener('uploadError', onUploadError);

Now you need to define the event handlers. The first event that you need to create should be the contentReady, which will enable the logging output in the uploader (the log messages will be output both to the YUI Logger and the Flash trace output), disallow multiple file selection and set file filters to filter user selection.


function handleContentReady () {
   // Allows the uploader to send log messages to trace, as well as to YAHOO.log
   uploader.setAllowLogging(true);
 
   // Restrict selection to a single file (that's what it is by default,
   // just demonstrating how).
   uploader.setAllowMultipleFiles(false);
  
   // New set of file filters.   
   var ff = new Array({description:"Images", extensions:"*.txt;*.jpg;*.png;*.gif"});
                     
   // Apply new set of file filters to the uploader.
   uploader.setFileFilters(ff);
  }

When the "Upload File" button is clicked, the upload function is called.


// Initiate the file upload. Since there's only one file, 
// I can use either upload() or uploadAll() call. fileList 
// needs to have been populated by the user.
function upload() {
 if (fileID != null) {
 uploader.upload(fileID, "http://localhost:8085/YUI_upload/oreilly_upload");
 fileID = null;
   }
}

When a file is selected, record the ID of the selected file, disable the uploader UI, display the name of the file and reset the progress bar.


// Fired when the user selects files in the "Browse" dialog
// and clicks "Ok".
function onFileSelect(event) {
 for (var item in event.fileList) {
     if(YAHOO.lang.hasOwnProperty(event.fileList, item)) {
   YAHOO.log(event.fileList[item].id);
   fileID = event.fileList[item].id;
  }
 }
 uploader.disable();

 var filename = document.getElementById("fileName");
 filename.innerHTML = event.fileList[fileID].name;
 var progressbar = document.getElementById("progressBar");
 progressbar.innerHTML = "";
}

The next function handles uploadProgress events and draws a progress bar of the correct size.


// Do something on each file's upload progress event.
function onUploadProgress(event) {
 prog = Math.round(300*(event["bytesLoaded"]/event["bytesTotal"]));
   progbar = "<div style=\"background-color: #f00; height: 5px; width: " + 
                                                                  prog + "px\"/>";
 var progressbar = document.getElementById("progressBar");
 progressbar.innerHTML = progbar;
}

Next, you need to handle the uploadComplete event, draw a full progress bar and re-enable the uploader UI.


// Do something when each file's upload is complete.
function onUploadComplete(event) {  
 uploader.clearFileList();
 uploader.enable();
 progbar = "<div style=\"background-color: #CCCCCC; height: 5px; width: 300px\"/>";
 var progressbar = document.getElementById("progressBar");
 progressbar.innerHTML = progbar;
         var filename = document.getElementById("fileName");
         filename.innerHTML = "";
}

The code without comments is shown below:


...
<style type="text/css">
     .uploadButton a, .clearButton a {
          display:block;
          width:100px;
          height:40px;
          text-decoration: none;
          margin-left:5px;
     }
     
     .uploadButton a {
          background: url("yui/resources/uploadFileButton.png") 0 0 no-repeat;
     }
     
     .clearButton a {
          background: url("yui/resources/clearListButton.png") 0 0 no-repeat;
     }
     
    .uploadButton a:visited, .clearButton a:visited {
          background-position: 0 0;
     }
     
    .uploadButton a:hover, .clearButton a:hover {     
          background-position: 0 -40px;
     }
     
    .uploadButton a:active, .clearButton a:active {
          background-position: 0 -80px;
     }
</style>

<div>
 <div id="fileProgress" style="border: black 1px solid; width:300px; height:40px;float:left">
  <div id="fileName" style="text-align:center; margin:5px; font-size:15px; width:290px; height:25px; overflow:hidden"></div>
  <div id="progressBar" style="width:300px;height:5px;background-color:#CCCCCC"></div>
 </div>
 <div id="uploaderUI" style="width:100px;height:40px;margin-left:5px;float:left"></div>
 <div class="uploadButton" style="float:left"><a class="rolloverButton" href="#" onClick="upload(); return false;"></a></div>
 <div class="clearButton" style="float:left"><a class="rolloverButton" href="#" onClick="handleClearFiles(); return false;"></a></div>
</div>

 <script type="text/javascript">

YAHOO.widget.Uploader.SWFURL = "yui/resources/uploader.swf";
     
     var uploader = new YAHOO.widget.Uploader( "uploaderUI", "yui/resources/selectFileButton.png" );
     
     uploader.addListener('contentReady', handleContentReady);
     uploader.addListener('fileSelect',onFileSelect)
     uploader.addListener('uploadStart',onUploadStart);
     uploader.addListener('uploadProgress',onUploadProgress);
     uploader.addListener('uploadCancel',onUploadCancel);
     uploader.addListener('uploadComplete',onUploadComplete);
     uploader.addListener('uploadCompleteData',onUploadResponse);
     uploader.addListener('uploadError', onUploadError);

    // Variable for holding the selected file ID.
     var fileID;
     
     function handleClearFiles() {
     uploader.clearFileList();
     uploader.enable();
     fileID = null;
     
     var filename = document.getElementById("fileName");
     filename.innerHTML = "";
     
     var progressbar = document.getElementById("progressBar");
     progressbar.innerHTML = "";
     }

     function handleContentReady () {
          uploader.setAllowLogging(true);
          uploader.setAllowMultipleFiles(false);     
          var ff = new Array({description:"Images", extensions:"*.txt;*.jpg;*.png;*.gif"});                             
          uploader.setFileFilters(ff);
     }

     function upload() {
     if (fileID != null) {
          uploader.upload(fileID, "http://localhost:8080/YUIupload/oreilly_upload");
          fileID = null;
       }
     }
 
     function onFileSelect(event) {
          for (var item in event.fileList) {
              if(YAHOO.lang.hasOwnProperty(event.fileList, item)) {
                    YAHOO.log(event.fileList[item].id);
                    fileID = event.fileList[item].id;
               }
          }
          uploader.disable();
          
          var filename = document.getElementById("fileName");
          filename.innerHTML = event.fileList[fileID].name;
          
          var progressbar = document.getElementById("progressBar");
          progressbar.innerHTML = "";
     }

    // Do something on each file's upload start.
     function onUploadStart(event) {
     
     }
     
     function onUploadProgress(event) {
          prog = Math.round(300*(event["bytesLoaded"]/event["bytesTotal"]));
            progbar = "<div style=\"background-color: #f00; height: 5px; width: " + prog + "px\"/>";

          var progressbar = document.getElementById("progressBar");
          progressbar.innerHTML = progbar;
     }
 
     // Do something when each file's upload is complete.
     function onUploadComplete(event) {  
          uploader.clearFileList();
          uploader.enable();
          
          progbar = "<div style=\"background-color: #CCCCCC; height: 5px; width: 300px\"/>";
          var progressbar = document.getElementById("progressBar");
          progressbar.innerHTML = progbar;

                var filename = document.getElementById("fileName");
          filename.innerHTML = "";
     }
 
     // Do something if a file upload throws an error.
     // (When uploadAll() is used, the Uploader will
     // attempt to continue uploading.
     function onUploadError(event) {           
     }
     
     // Do something if an upload is cancelled.
     function onUploadCancel(event) {
     }
     
     // Do something when data is received back from the server.
     function onUploadResponse(event) {  
          alert("Server response successfully received!");
     }

</script>
...

For this application you can use the COS described in the article COS and SWFUpload for End-to-end Java File Upload. The result of this application is shown in the figure below.

Java File Upload

Java Upload with Postlet Applet

Postlet is a Java applet used for uploading files to Web servers. It supports multiple file uploading using a nice, easy-to-use design.

Postlet provides four main features:

  • File progress bar
  • Error checking
  • Easy selection and upload of multiple files
  • Resizing of images over a set size

To start, you must download Postlet, the Java applet upload, from postlet.com. Extract the postlet.jar under your Web application.

The applet is customizable through a set of parameters:

  • destination: the URL to your servlet that will accept file upload
  • language: the language to use for Postlet's user interface
  • backgroundcolour: the color to use for Postlet background
  • tableheadercolour: the color to use for the text of the Table Headers
  • tableheaderbackgroundcolour: the color to use for the background of the Table Headers
  • fileextensions: a list of the file extensions
  • warnmessage: enables the ability to show a warning message once the upload button is pressed. Its value can be "true" or "false."
  • autoupload: enables the ability to automatically upload files once they are selected. Its value can be "true" or "false."
  • helpbutton: enables the ability to show a help button. It works on versions newer than 0.10.0, and its value can be "true" or "false."
  • maxpixels: the maximum number of pixels allowed for GIF, JPEG and PNG images when there are uploaded. If files exceed this limit, they are resized to the set limit. If they are resized GIF images, they are uploaded as PNG images. It works on versions newer than 0.13.
  • helppage: the URL to show if the user clicks the help button. The default URL is to http://www.postlet.com/help/.
  • maxthreads: the maximum number of connections to use. It can take values from 1 to 5.
  • Endpage: the URL to take the user to once upload has completed.
  • Failedfilesmessage: enables the ability to show the popup message listing the files that failed to upload

A possible configuration is listed below:


<applet name="postlet" code="Main.class" 
        archive="./applets/postlet.jar" width="850" height="150" mayscript>
  <param name = "maxthreads" value = "5" />
  <param name = "language" value = "" />
  <param name = "type" value = "application/x-java-applet;version=1.3.1" />
  <param name = "destination" 
         value = "http://localhost:8085/PostletUpload/applet_upload" />
  <param name = "backgroundcolour" value = "56328145" />
  <param name = "tableheaderbackgroundcolour" value = "24279327" />
  <param name = "tableheadercolour" value = "0" />
  <param name = "warnmessage" value = "false" />
  <param name = "autoupload" value = "false" />
  <param name = "helpbutton" value = "false" />
  <param name = "fileextensions" value = "Image Files,jpg,gif,jpeg" />
  <param name = "endpage" value = "[*** ENDPAGE URL***]" />
  <param name = "helppage" 
         value = "http://www.postlet.com/help/?thisIsTheDefaultAnyway" />
</applet>

When the uploads ends, a JavaScript function can fire up a message:


<script type="text/javascript">      
     function postletFinished(){ 
       alert("Postlet Applet Succesfully Accomplished its Job!"); }
    </script>

For this application (on the server side) you can use the COS described in this article COS and SWFUpload for End-to-End Java File Upload. Notice the messages returned by the server should by specific to Postlet Upload. You can see the entire list of possible responses. The COS implementation for Postlet Upload is:


public class AppletUploadServlet extends HttpServlet {

 protected void processRequest(HttpServletRequest request, 
    HttpServletResponse response) throws ServletException, IOException {        
     
  final int permitedSize = 314572800;  //~ 300 MB bytes
  final String[] extensions = {".zip",".xls"};
         
  StringBuffer answer = new StringBuffer();
  answer.append("POSTLET REPLY\nPOSTLET:YES\nEND POSTLET REPLY\n");      
       
  PrintWriter out = response.getWriter();
  response.setContentType("text/html;charset=UTF-8");
  response.setHeader("Cache-Control", "no-cache");
  response.setHeader("Pragma", "No-cache");
  response.setDateHeader("Expires",0);  
    
  try{               
     String strDirectory = "files";
     String uploadPath = request.getRealPath("//WEB-INF//"+strDirectory+"//");

    //or, like this, from web.xml       
     String uploadPath_rezerva = request.getRealPath(getServletConfig().
                 getInitParameter("uploadPath"));

     MultipartRequest multipartRequest = new MultipartRequest(request,
           uploadPath, permitedSize, "ISO-8859-1", new DefaultFileRenamePolicy()); 
          
     Enumeration files = multipartRequest.getFileNames(); 
   
 String extension1 = "";
        String extension2 = "";
        String filename = "";
          
        while (files.hasMoreElements()) 
        { 
               String name = (String)files.nextElement(); 
               filename = multipartRequest.getFilesystemName(name); 
               String originalFilename = multipartRequest.getOriginalFileName(name); 
                                                
      extension1 = filename.substring(filename.length() - 4, filename.length());
             extension2 = originalFilename.substring(originalFilename.length() - 4, 
             originalFilename.length());
                                                            
                //use O'Reilly COS
                File currentFile = multipartRequest.getFile(name);
                }
                         
       out.println(answer);

       }catch (Exception exception)
          {                     
   answer.delete(0, answer.length());
          answer.append("POSTLET REPLY\nPOSTLET:NO\nPOSTLET:SERVER ERROR\n
                               POSTLET:ABORT ALL\nEND POSTLET REPLY\n");
          
          out.println(answer);
   } finally { if(out != null) {out.close();} }     
   } 
}

The result of this application is shown in the figure below:

Java Upload

Java Upload with PrimeFaces

In the past couple of year, I've noticed a lot of interest in the PrimeFaces upload solution. I can't say that I'm surprised, since it is a very good-looking upload solution that is easy to configure and use. Therefore, I've decided to provide a small guide to implementing the PrimeFaces upload under a Tomcat 6 Web application.

You will need the following JARs, under your /lib folder:

  • primeface-2.2.RC2.jar (this is what I used, but you can take the latest PrimeFaces library from the PrimeFaces site).
  • jsf-api-2.0.2-FCS.jar (again, use the latest version if you think that you need it)
  • jsf-impl-2.0.2-FCS.jar
  • el-api-2.2.jar
  • el-impl-2.2.jar
  • commons-io-1.4.jar
  • commons-fileupload-1.2.jar

To start, I've configured the application descriptor and web.xml (depending on the PrimeFaces version, these configurations may be slightly different). In this descriptor, I've configured the PrimeFaces upload filter:


<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" 
    "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
<web-app>            
    <context-param>
        <description>Context param for JSTL 1.2 to work in Tomcat 6 sun RI
        </description>
        <param-name>com.sun.faces.expressionFactory</param-name>
        <param-value>com.sun.el.ExpressionFactoryImpl</param-value>
    </context-param>
    <context-param>
        <description>Parameter required by Mojarra 2.0</description>
        <param-name>com.sun.faces.allowTextChildren</param-name>
        <param-value>true</param-value>
    </context-param>
    <context-param>
        <param-name>javax.faces.VALIDATE_EMPTY_FIELDS</param-name>
        <param-value>true</param-value>
    </context-param>    
    <filter>
        <filter-name>PrimeFaces FileUpload Filter</filter-name>
        <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
        <init-param>
            <param-name>thresholdSize</param-name>
            <param-value>2097152</param-value>
        </init-param>      
    </filter>
    <filter-mapping>
        <filter-name>PrimeFaces FileUpload Filter</filter-name>
        <servlet-name>Faces Servlet</servlet-name>
    </filter-mapping>  
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>   
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/faces/*</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>faces/index.xhtml</welcome-file>
    </welcome-file-list>   
</web-app>

Next, I wrote a simple JSF page to test the PrimeFaces upload component:


<?xml version="1.0" encoding="UTF-8"?>                              

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.prime.com.tr/ui">
<h:head>
</h:head>
 <h:body>
 <h:outputText value="Select the files to upload (maxim 2MB):"/>
 <p:growl id="uploadMessages" showSummary="true" showDetail="true"/>
 <h:form enctype="multipart/form-data" prependId="false">
  <p:fileUpload update="uploadMessages"   
                fileUploadListener="#{fileUploadController.handleFileUpload}" 
                sizeLimit="2097152" 
                multiple="true" 
                label="choose" 
                allowTypes="*.jpg;*.png;*.gif;" 
                description="Images"/>  
 </h:form>
 </h:body>
</html>

As you can see, p:fileUpload is very flexible and customizable, allowing us to specify upload characteristics with a few simple attributes. Going further, I need a managed bean capable of dealing with upload itself. A possible implementation is listed below (probably not the best, but for sure not the worst):


package com.extensions;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.faces.FacesException;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import org.primefaces.event.FileUploadEvent;

@ManagedBean(name = "fileUploadController")
@RequestScoped
public class uploadFilesBean {
   
    //Primitives
    private static final int BUFFER_SIZE = 6124;    
    private String folderToUpload;
    
    /** Creates a new instance of UploadBean */
    public uploadFilesBean() {
    }
    
    public void handleFileUpload(FileUploadEvent event) {
       
    ExternalContext extContext=FacesContext.getCurrentInstance().getExternalContext();
            
    File result = new File(extContext.getRealPath("//WEB-INF//files//" + 
          event.getFile().getFileName()));
    //System.out.println(extContext.getRealPath("//WEB-INF//files//" + 
    //      event.getFile().getFileName()));

    try {
        FileOutputStream fileOutputStream = new FileOutputStream(result);

        byte[] buffer = new byte[BUFFER_SIZE];

        int bulk;
        InputStream inputStream = event.getFile().getInputstream();
        while (true) {
               bulk = inputStream.read(buffer);
               if (bulk < 0) {
                   break;
                }
               fileOutputStream.write(buffer, 0, bulk);
               fileOutputStream.flush();
         }

        fileOutputStream.close();
        inputStream.close();

       FacesMessage msg = new FacesMessage("Succesful", event.getFile().getFileName()
                                                                  + " is uploaded.");
        FacesContext.getCurrentInstance().addMessage(null, msg);

        } catch (IOException e) {
            e.printStackTrace();

            FacesMessage error = new FacesMessage(FacesMessage.SEVERITY_ERROR, 
                                                 "The files were not uploaded!", "");
            FacesContext.getCurrentInstance().addMessage(null, error);
     }       
   }    
}

The uploaded files go to the /WEB-INF/files folder. Here it is a nice screenshot of PrimeFaces upload.

Java Upload

The PrimeFaces upload example in this section was simple. Visit the PrimeFaces ShowCase site, where you can see more types of uploads.

Java Upload with GWTUpload

Another way to upload files is using the GWTUpload upload library. GWTUpload is a library for uploading files to Web servers; it can display a progress bar that displays the upload status. In addition, you can get the size of the uploaded file, the original filename in the client's filesystem, the content type passed by the browser, the bytes transferred, and so on.

Java Upload

GWTUpload has two components:

  1. the server side, written in Java with servlet and utility classes
  2. the client side, written in JavaScript using GWT

The following bullets characterize this upload mechanism:

  • the server side could be implemented in any language
  • the client side can be used from GWT applications, or from JavaScript without knowing GWT
  • ability to upload single and multiple files
  • ability to customize the progress bar or implement another one
  • ability to customize the choose button
  • easy to use

This upload uses JDK 6 and can be easily tested under the Tomcat 6 container. The libraries used include:

In this section, you will develop an application using GWTUpload based on the simplest scenario. A user selects a file from his computer, uploads the file and gets basic feedback about the uploaded file.

First, on the client side, I have a basic HTML upload form in the index.html page, which you have probably seen many times:


...
  <form enctype="multipart/form-data" action="./gwt_upload"   
    method="POST"> 
    File to be uploaded : 
    <input type="file" name="userfile">
    <br>
    <input type="submit" value="Upload">
  </form>
...

The next step is to configure the application descriptor file (web.xml):


<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">

<web-app>

    <display-name>Numele aplicatiei</display-name>

    <context-param>
     <param-name>maxSize</param-name>
     <param-value>3145728</param-value>
    </context-param>
    <context-param>
     <param-name>slowUploads</param-name>
     <param-value>200</param-value>
    </context-param>

  <servlet>
    <servlet-name>uploadServlet</servlet-name>    
    <servlet-class>com.extensions.GWTUploadServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>uploadServlet</servlet-name>
    <url-pattern>/gwt_upload</url-pattern>
  </servlet-mapping>

</web-app>

As you can see, I have configured the maximum size of the upload request:


...    
    <context-param>
     <param-name>maxSize</param-name>
     <param-value>3145728</param-value>
    </context-param>
...

If you are working in development mode, it is useful to slow down the uploads in fast networks by putting the number of milliseconds to sleep in each block received in the server, or you can use false or 0 if you don't want to use slow uploads:


...    
    <context-param>
     <param-name>slowUploads</param-name>
     <param-value>200</param-value>
    </context-param>
...

On the client side, when a user clicks on the upload button, the action attribute of the form field calls a Java servlet that is able to deal with HTTP requests. On the server side, in the GWTUploadServlet.java servlet, the first thing I have to do is to maintain a list with the received files and their content types. We can do this with just a few lines:


...
public class GWTUploadServlet extends UploadAction {

  private static final long serialVersionUID = 1L;
  Hashtable<String, String> receivedContentTypes = new Hashtable<String, String>();
  Hashtable<String, File> receivedFiles = new Hashtable<String, File>();
...

The next step is to override the executeAction method to save the received files in a custom place and then delete these items from the session. Each item type is determined by calling the isFormField boolean method. Once you know the item type, you can choose how you process it forward:


...
  @Override
  public String executeAction(HttpServletRequest request, List<FileItem> sessionFiles) throws UploadActionException {
    String response = "";
    int cont = 0;
    for (FileItem item : sessionFiles) {
      if (false == item.isFormField()) {
        cont ++;
        try {
          /// Create a new file based on the remote file name in the client
          // String saveName = item.getName().replaceAll("[\\\\/><\\|\\s\"'{}()\\[\\]]+", "_");
          File file =new File(request.getRealPath("//WEB-INF//files") + "//" + item.getName());
          
          /// Create a temporary file placed in /tmp (only works in unix)
          // File file = File.createTempFile("upload-", ".bin", new File("/tmp"));
          
          /// Create a temporary file placed in the default system temp folder
          //File file = File.createTempFile("upload-", ".bin");
          item.write(file);
          
          /// Save a list with the received files
          receivedFiles.put(item.getFieldName(), file);
          receivedContentTypes.put(item.getFieldName(), item.getContentType());
          
          /// Compose a xml message with the full file information which can be parsed in client side
          response += "<file-" + cont + "-field>" + item.getFieldName() + "</file-" + cont + "-field>\n";
          response += "<file-" + cont + "-name>" + item.getName() + "</file-" + cont + "-name>\n";
          response += "<file-" + cont + "-size>" + item.getSize() + "</file-" + cont + "-size>\n";
          response += "<file-" + cont + "-type>" + item.getContentType()+ "</file-" + cont + "type>\n";
        } catch (Exception e) {
          throw new UploadActionException(e);
        }
      }
    }
    
    /// Remove files from session because I have a copy of them
    removeSessionFileItems(request);
    
    /// Send information of the received files to the client.
    return "<response>\n" + response + "</response>\n";
  }
...

Now, if I want to get the content of an uploaded file, I need to override the getUploadedFile method:


...
  @Override
  public void getUploadedFile(HttpServletRequest request, HttpServletResponse response) throws IOException {
    String fieldName = request.getParameter(PARAM_SHOW);
    File f = receivedFiles.get(fieldName);
    if (f != null) {
      response.setContentType(receivedContentTypes.get(fieldName));
      FileInputStream is = new FileInputStream(f);
      copyFromInputStreamToOutputStream(is, response.getOutputStream());
    } else {
      renderXmlResponse(request, response, ERROR_ITEM_NOT_FOUND);
   }
  }
...  

Finally, remove a file when the user sends a delete request:


...
  @Override
  public void removeItem(HttpServletRequest request, String fieldName)  throws UploadActionException {
    File file = receivedFiles.get(fieldName);
    receivedFiles.remove(fieldName);
    receivedContentTypes.remove(fieldName);
    if (file != null) {
      file.delete();
    }
  }
}

The result of this application is shown below:

Java Upload

Java Upload with JUpload Applet

JUpload is a Java applet used for uploading files to Web servers using the standard HTTP POST command, or in FTP mode JUpload can directly write the file on the target server. It supports multiple-file uploading using a nice, easy-to-use design, and it has a lot of configuration parameters that allow for easy adaptation to your specific needs.

JUpload provides seven main features:

  • File progress bar
  • Error checking
  • Easy selection and upload of multiple files
  • FTP and HTTP (POST) capabilities
  • Multilingual: more than 20 languages
  • Control of allowed file extension
  • Picture management (resizing, rotation, format change)

To start, you must download the JUpload stable release from the project page. In the download section, you will find a link to the project download page. (At the time of writing, the JUpload stable version was jupload-5.0.7-src-5.0.7.zip.) The applet is mapped under wjhk.jupload.jar. This can be found under the /site directory. You need to copy this archive under your project root.

The applet is customizable through a set of parameters. Here are just some of these parameters:

  • afterUploadTarget: allows you to select a specific target frame when redirecting to afterUploadURL
  • afterUploadURL: allows the applet to change the current page to another one after a successful upload
  • allowedFileExtensions: allows the caller to specify a list of file extensions
  • debugLevel: The normal production output is 0. The higher the number is, the more information is displayed in the log window.
  • fileChooserIconSize: allows you to control the size of icons, in pixels, in the file chooser
  • fileChooserImagePreview: allows you to control whether a preview is available for the picture in the file chooser
  • ftpCreateDirectoryStructure: allows you to control whether the directory structure on the client side must be created on the server side
  • ftpTransfertBinary: allows you to control whether the upload should be done in binary or ASCII mode
  • ftpTransfertPassive: allows you to control whether the upload should be done in FTP passive mode, or in active mode (where the FTP server opens a connection to the client, to do the upload)
  • maxChunkSize: defines the maximum size of an upload
  • maxFileSize: identifies the maximum size that an uploaded file may have
  • postURL: specifies the target URL toward which the files should be uploaded
  • showStatusBar: controls if the status bar is shown in the applet. If shown, the status bar provides information about the current transfer speed and estimated time of completion.
  • uploadPolicy: contains the class name for the UploadPolicy that should be used

The JUpload applet has many parameters. For more details, visit this page.

Depending on the list of parameters added, the JUpload applet can be configurated in two modes: a basic mode and a picture mode. Below, you can see a possible basic mode applet configuration:


. . .
  <applet
        code="wjhk.jupload2.JUploadApplet"
        name="JUpload"
        archive="./applet/wjhk.jupload.jar"
        width="640"
        height="300"
        mayscript="true"
        alt="The java pugin must be installed.">           
        <param name="postURL" value="./oreilly_upload" />            
        <param name="showLogWindow" value="false" />            
  </applet>
. . .

The picture mode adds some nice and useful capabilities using another existing UploadPolicy, the PictureUploadPolicy:

  • browse files with picture preview, in the file chooser.
  • rotate pictures, quarter by quarter.
  • resize picture, according to a maximum allowed height and/or width
  • change the file format (for instance .gif to .png)
  • send (or not) the picture metadata
  • preview pictures, from the 'file to upload' list

Below, you can see a possible picture mode applet configuration:


. . .
  <applet code="wjhk.jupload2.JUploadApplet"
          archive="./applet/wjhk.jupload.jar" width="640" height="400" alt="The java pugin must be installed."
          mayscript="true">
          <param name="postURL" value="./oreilly_upload" />
          <param name="maxChunkSize" value="500000" />
          <param name="uploadPolicy" value="PictureUploadPolicy" />
          <param name="nbFilesPerRequest" value="1" />
          <param name="maxPicHeight" value="900" />
          <param name="maxPicWidth" value="700" />
          <param name="debugLevel" value="0" />
          <param name="showLogWindow" value="false" />
          Java 1.5 or higher plugin required. 
   </applet>
. . .

By providing the <uploadPolicy> parameter within the APPLET tag, you can select another class that implements the UploadPolicy interface found at the UploadPolicy page.

On the official JUpload project site, you can find more details about how to customize the JUpload applet, choose the best UploadPolicy for you, or if those customizations are not enough, create a new Java Upload Policy.

For this application (on the server side) you can use the COS described in COS and SWFUpload for End-to-end Java File Upload. The COS implementation for JUpload is:


protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {        
     
   final int permitedSize = 314572800;  //~ 300 MB in bytes
                
   PrintWriter out = response.getWriter();
   response.setContentType("text/html;charset=UTF-8");
   response.setHeader("Cache-Control", "no-cache");
   response.setHeader("Pragma", "No-cache");
   response.setDateHeader("Expires",0);                       
    
    try{               
       String type = "";
       String name = "";
       String originalFilename = "";
       String extension1 = "";
       String extension2 = "";
       String filename = "";

       String strDirectory = "files";
       String uploadPath = request.getRealPath("//WEB-INF//"+strDirectory+"//");

       //the path can also be specified in the web.xml and from there it can be extracted like this
       String uploadPath_2 = request.getRealPath(getServletConfig().getInitParameter("uploadPath"));

       //constructs a new MultipartRequest to handle the specified request
       MultipartRequest multipartRequest = new MultipartRequest(request, uploadPath, permitedSize, "ISO-8859-1", new DefaultFileRenamePolicy()); 
          
       //extract the uploaded files as an Enumeration
       Enumeration files = multipartRequest.getFileNames();               
          
          //getting a few details about each uploaded file    
          while (files.hasMoreElements()) 
              { 
                 name = (String)files.nextElement();
                 type = multipartRequest.getContentType(name); 
                 filename = multipartRequest.getFilesystemName(name); 
                 originalFilename = multipartRequest.getOriginalFileName(name);                 
                 
                 //extract the file extension - this can be use to reject a undesired file extension                      

                 extension1 = filename.substring(filename.length() - 4, filename.length());
                 extension2 = originalFilename.substring(originalFilename.length() - 4, originalFilename.length());

                 //return a File object for the specified uploaded file                   
                 File currentFile = multipartRequest.getFile(name);
                 //InputStream inputStream = new BufferedInputStream(new FileInputStream(currentFile));
                 if(currentFile == null) {
                      out.println("ERROR: There is no file selected!\n");
                      return;
                    }

                 //checking the file extensions according to the MIME types
                 if((type.equals("text/plain") || type.equals("image/gif") || type.equals("image/pjpeg")
                   || type.equals("image/x-png") || type.equals("image/jpeg"))) {       
                     //show a few details about the uploaded file                                           
                   } else {
                          //the file has a different extension, reject it!
                          //you have to write a code snippet to delete this file!!!
                          out.println("ERROR: Wrong file type!\n");
                          }

                 out.println("SUCCESS\n");         
                 }                        

       }catch (Exception exception)
          {                         
       response.sendError(response.SC_METHOD_NOT_ALLOWED);
       } finally { if(out != null) {out.close();} }         
}  

The JUpload applet can test if the server has detected an error in the upload progress. In other words, the applet will find an error if at least one line returned in the server response begins with "ERROR: " as shown below:


out.println("ERROR: Wrong file type!\n");

The applet will display this message to the user using an alert box:

Java Upload

If everything goes well and the server accepts the upload, the applet will receive a "success" message:

out.println("SUCCESS\n");

The result of this application is shown below:

  1. Basic mode applet

    Java Upload

  2. Picture mode applet

    Java Upload

Conclusion

In this article, you have seen a set of five upload solutions for Java Web applications:

  • YUI Uploader
  • GWTUpload
  • Postlet Applet
  • JUpload Applet
  • PrimeFaces upload

All these upload components bring very useful facilities for Java Web developers.

Sitemap | Contact Us