How to upload a file

This article discusses how to include file uploading capabilities in Nexaweb applications that use
Nexaweb's Java Client. Developers deploying applications using the Java client have tried several
solutions to overcome the tight security of using Java in the browser, where access to the file system
is prohibited by the Java Applet unless the Applet is signed and the user accepts the additional
privileges that Applet is requesting.

Overcoming these challenges can be done several ways:

  1. Sign your Nexaweb application to gain the privileges that are needed to browse the file system.
  2. Popup a separate browser that has a file upload dialog.
  3. Use Ajax to do the file uploading process.

In this article, I cover using Ajax to do file uploading. Why did I pick this way?  The Ajax method has
the least number of steps to complete in order to get the functionality to work.
Also, I have heard this Ajax thing is really cool.

Developer Resources:

Sample Application Screenshots


The rest of this article details the steps you will need to complete to get the file upload functionality working in your application.

Third party code

The example includes four third party libraries that make the file uploading process possible.

Our code

Supplied in the sample application are several files you will need to include in your Nexaweb application
in order to get the upload functionality to work.

  • Client Code
    • com.nexaweb.mco.upload.FileUploader.java
    • com.nexaweb.mco.upload.FileUploadListener.java
  • Web Resources
    • thickbox.css
    • loading.gif
    • nexaweb.file.uploader.all.js
    • blank.html

The client code is located in the src-client directory, you will need to place these in your application
client code directory. The web resources are included in the fileupload directory; place these inside
the WebContent directory of your Nexaweb application.

Your Code

You will need to write the following code to use the file uploading functionality in your application:

Inclusions of an MCO tag in a XAL document that loads the
com.nexaweb.mco.upload.FileUploader class.  The ID of the MCO can be anything you want, but
you will need to connect the ID for the MCO declared in XAL to the ID of the MCO you ask for from
the McoContainer. In the code snippets below, the ID of the MCO is "fileUploadServlet".

<xal>
     <mco:mco xmlns:mco="http://openxal.org/core/mco" id="fileUploadServlet" src="com.nexaweb.mco.upload.FileUploader"/>
</xal>

To open the file upload dialog, get the FileLoader MCO from the MCO container and call its
 startUpload method.  The startUpload method takes three parameters:

  1. The location of the file uploading servlet, in the sample application this is servlet/UploadServlet.  The URL is relative to the HTML file that loaded the Nexaweb application.
  2. The title of the file Upload dialog.
  3. A Listener to handle events that are generated during the upload process. The listener will need
    to implement the FileUploadListener interface as shown below.  As a result of the way the
    callback from the JavaScript needs to be handled, this CANNOT be an anonymous inner class.
public class FileUploadTesters extends AbstractMco{
    public Element _output = null;
 
    public void testFileUpload(Element output) {     
         _output = output;
 
        ClientSession clientSession = this.getSession();
        FileUploader fileUploader = 
              (FileUploader)clientSession.
                getMcoContainer().get("fileUploadServlet");    
 
        fileUploader.startUpload("servlet/UploadServlet", 
               "Upload your Excel Spreadsheet", 
               new Listener());
    }
}

The uploading functionality will call a listener class supplied when one of three things happens:

  1. uploadSuccess - The file is uploaded successfully.
  2. uploadError - An error occurred during the uploaded process.
  3. uploadQuit - The user clicks the Close button in the file upload dialog.

The data parameters of the listener methods contain the contents of the file-upload-request response.  You can use this data to communicate information about error code and messages, file names and size,
or anything else you may have.

 
    public class Listener implements FileUploadListener{
        public void uploadError(String data) {
        }
 
        public void uploadQuit() {
        }
 
        public void uploadSuccess(String data) {
        }
    }

 

You will need to change your application's start page to include the following lines of code. 
The start page in most Nexaweb applications is usually "index.jsp"

<!-- THIS IS THE CODE TO INCLUDE  --> <!-- INTO YOUR HTML APPLICATION -->
<script src="javascript/nexaweb.file.uploader.all.js"> </script>    
<link href="javascript/thickbox.css" type="text/css" rel="stylesheet">
<!-- THIS IS THE CODE TO INCLUDE --> <!-- INTO YOUR HTML APPLICATION -->

The server-side

This example includes a file upload servlet I downloaded online (http://www.servletsuite.com/servlets/upload.htm). This servlet makes it simple to download a file and store it in the local file system.  Apache also has file upload functionality that can be downloaded at http://commons.apache.org/fileupload/using.html. Use this file from Apache if you are looking
to do more complex functionality after the file is downloaded such as,
turn an Excel spreadsheet into a data source for a table or analyze a text file.

Inside of the sample application the resources that are needed to handle the file uploading functionality from the server-side include the following.

  • WebContent
    • upload.conf - configures the
    • upload.html - test the uploading functionality outside of Nexaweb with just HTML.
    • WEB-INF
      • web.xml - Need to add the servlet mapping for the file uploading servlet
      • lib
        • uploadPackage.jar
Note: You will need to customize the path to your projects upload configuration file that is supplied in the project. This is a result of the file upload functionality that is specific to Servletsuite.com. 
<init-param>
    <param-name>config</param-name>
    <param-value>  <!-- Place the path to the config file here --> </param-value>
</init-param>

Customizing the functionality

There are several places this functionality can be customized to get everything just the way you like it. 

  • Customizing the look and feel of the upload dialog, change the thickbox.css and / or the string
    that represents the dialog that is located at the end of the nexaweb.file.upload.all.js file
  • Change the message related to the file upload dialog. The string for the dialog in nexaweb.file.upload.all.js
  • Remove/change the information dialogs that open when the file upload succeeds or fails.  The "alerts" are in the "ajaxFileUpload()" function in the nexaweb.file.upload.all.js
  • Sending additional parameters to the file upload request. Add hidden input fields to the upload form.

Issues I ran into

I ran into the following issues integrating the Ajax and Java functionality, which will be helpful to know when trying to implement your own functionality:

  • Calling back into the the Java client occurs on a different thread than the one that normal
    Nexaweb events happen on.  This causes issues with using class loaders or interacting with
    the Nexaweb DOM.  You can solve this problem by using the
    getSession().getUiUpdateQueue() object.
  • Opening up dialogs over the Java applet works in Firefox only.  IE and other browsers
    have what is been called "submarining" issue where the applet is always drawn on top.  
    To overcome this, hide the applet while the dialog is displayed, using:
    document.applets[0].style.display = "none"; then turn it back on afterwards
    using: document.applets[0].style.display = "" .
  • Calling into the JavaScript environment in Windows Safari and Opera causes the
    browser to reload the application.  This needs to be looked into more.
  • In Opera, getting the Session object from the Applet will return null. This can be
    overcome by passing the MCO object that you will need later when calling from JavaScript back into Java.

Summary

This example demonstrates how to upload a file using Ajax but the sample also demonstrates how to communicate between the Nexaweb Java client and the HTML / Javascript environment.  Developers can use this process to do a lot more things like displaying a Google Map and using Nexaweb Java client
as a distributor of the real-time data.

Nexaweb

By Bob Buffone