File Upload Utility

This utility provides a demonstration of how a combination of a Java Bean embedded in the Oracle Forms Java Client and Java called from the Oracle Forms Services on the middle tier can be used to transfer files from the browser client machine, onto the middle tier machine. The utility consists of three parts:

  1. A Client side Java Bean which selects, encodes and transfers a file from the browser client.  This is the UploadClient Java Bean
  2. Some server side Java classes which handle the receiving of the transferred file, decoding and writing it back to disk on the server.
  3. A PL/SQL library which provides the glue between the two sets of Java.

The Java Bean portion must reside in a signed JAR file at deployment time since it performs an operation that is outside of the Java sandbox for non trusted code. This distribution ships with a signed version of the JAR file.

Modules In This Demo

The FileUpload demo consists of the following files (relative directories shown in brackets):

  1. fileuploader.fmb/fmx [forms] - The demo form
  2. fileupload90.pll [forms] - a PL/SQl library with all of the required code to integrate upload into your own applciations
  3. FileUploader.java, FileUploaderProgressBar.Java [src/oracle/forms/demos/uploadclient] - source code for the Upload JavaBean
  4. FormsDecoder.java, FormsDecoder.java [src/oracle/forms/demos/uploadserver] - source code for the server side code that writes the uploaded files to disk
  5. uploadclient.jar [classes] - the compiled and jarred java classes for the client side bean.
  6. uploadserver.jar [classes] - compiled and jarred java classes for the server side code

The doc directory and the classes directory contain the JavaDoc for the code and the compiled classes respectively

Reusing the code

Setting up Forms Services

In order for an application to be able to reuse the Fileupload code provided, some changes need to be made to the environment that Forms Services on the middle tier is running with.  The easy way to do this is to create a custom environment file which you can then reference from the relevant configuration in the formsweb.cfg file.

This environment file should make sure that the CLASSPATH used by Forms Services includes the uploadserver.jar file.  For example: 

#fileupload.env
#Environment file used to setup the FileUpload Demo
ORACLE_HOME=c:\oracle\DevSuiteHome
PATH=c:\oracle\DevSuiteHome\jdk\jre\bin\classic;c:\oracle\DevSuiteHome\bin
CLASSPATH=c:\oracle\DevSuiteHome\\forms\\demos\jars\uploadserver.jar;c:\oracle\DevSuiteHome\jdk\jre\lib\rt.jar
FORMS_path=c:\oracle\DevSuiteHome\\forms\\demos\lib;c:\oracle\DevSuiteHome\\forms\\demos\fileupload\forms

An entry in the formsweb.cfg file to call the FileUplaod demo might look like this, note the addition of the custom env file fileupload.env:

[FileUpload]
pageTitle=OracleAS Forms Services - FileUpload Sample
IE=jinitiator
baseHTMLJInitiator=demobasejini.html
archive_jini=frmall_jinit.jar,/formsdemo/jars/uploadclient.jar 
width=675
height=480
separateFrame=false
splashScreen=no
lookAndFeel=oracle
colorScheme=blue
form=fileuploaderforms/java
background=/formsdemo/images/blue.gif
envFile=fileupload.env

Adding the code to your Form

Reusing the FileUpload utility within your own applications requires the following steps.

  1. Attach the FileUpload.pll library (shipped in the FileUpload\forms directory) to the form that needs upload capability
  2. Create a new BeanArea on one of your canvases. The bean is invisible and so you can set the size to 1x1. The BeanArea should be placed into a block with the Single Record property set to Yes. This will ensure that the bean is instanciated as soon as the Form is started. You can create a brand new block to hold the bean if you wish.
  3. Set the Implementation Class property of the new BeanArea to oracle.forms.demos.uploadclient.FileUploader
  4. Create a WHEN-CUSTOM-ITEM-EVENT trigger on the BeanArea with the code:

begin
FileUploader.eventHandler(:system.custom_item_event,get_parameter_list(:system.custom_item_event_parameters));
end;

  1. Create a user named trigger e.g. FILEUPLOADER_CALLBACK which the upload utility will execute when the upload is complete or if the upload fails for some reason. We need this trigger because the upload is an asynchronous process, and the trigger that calls the FileUploader.UploadFile() function is not blocked until the upload is finished. A sample callback trigger might look like.

/*----------------------------------------------------*
* Sample Callback trigger for FileUploader
* You should always implement a check on the status
* to make sure that the upload has worked.
*
* This trigger will only be executed once the upload
* has finished or aborted
*---------------------------------------------------*/
Begin
 if FileUploader.getStatus = FileUploader.FINISHED then
  message(FileUploader.getSourceFile || 'was uploaded');
elsif FileUploader.getStatus = FileUploader.FAILED then
  message('Upload Failed because: '||FileUploader.getError);
 end if;
end;

  1. Register the Bean and the Callback trigger by calling FileUploader.init(<BeanArea>,<TriggerName>). This can be done in the startup code for the form, or just before invoking an upload. However, you must call Init() before uploading. A sample call to Init might look like:

FileUploader.init('UPLOAD.FILE_UPLOAD_BEAN','FILEUPLOADER_CALLBACK');

  1. Finally write the code to call the upload. You can either call FileUploader.UploadFile() to display a selection dialog on the client, or FileUploader.UploadNamedFile() to upload a specific file.

FileUploader.UploadFile('d:\temp\uploaded');

Warning: If you intend to use the FileUpload utility in your own applications, We recommend that you re-sign the UploadClient PJC with your own x509 certificate.

The FileUpload PL/SQL API

All of the code required for the FileUpload facility is exposed through the FileUploader package in the FileUpload.pll library. The FileUpload PLL also contains several other packages which provide interfaces to the Java classes used by the utility. These are called via FileUpload and should not be called directly.

Main Functions in the FileUploader package

Function Purpose
Init (BeanName in VARCHAR2, CallbackTrigger in VARCHAR2)

Defines the settings for the upload utility This must be called before upload can be used.

  • BeanName should contain the block and field name of the BeanArea that you've defined for the bean
  • CallbackTrigger will contain the name of a user defined trigger that will be call ed once an upload is finished or aborted
UploadFile (DestinationDirectory in VARCHAR2, DestinationFilename in VARCHAR2, SourceDirectory in VARCHAR2);

Displays a file dialog on the client, allows the user to select a file and uploads that file to the middle tier.

  • DestinationDirectory is the directory on the middle tier that the uploaded file will be written to. You must have write access to this directory
  • DestinationFilename [optional] is the name for the file once it has been uploaded. If omitted the file name on the client is used.
  • SourceDirectory [optional] is the initial directory for the file dialog to be set to. If this is not set, the utility remembers the last directory that you browsed in this session
UploadNamedFile (FileName in VARCHAR2, DestinationDirectory in VARCHAR2, DestinationFilename in VARCHAR2)

Directly uploads a named file from the client without displaying a file selection dialog.

  • Filename path to and name of file to upload
  • DestinationDirectory is the directory on the middle tier that the uploaded file will be written to. You must have write access to this directory
  • DestinationFilename [optional] is the name for the file once it has been uploaded. If omitted the file name on the client is used.
GetStatus return PLS_INTEGER

Returns the current status of the upload as one of the following constants:

  • FileUploader.UPLOADING: The bean is currently sending Data
  • FileUploader.FINISHED: The bean is not currently Uploading
  • FileUploader.FAILED: The bean is not currently Uploading and the last upload attempt failed (usually because the requested file did not exist)

GetStatus is mainly called from the Callback trigger which will be executed after a successful and a failed upload

GetError return VARCHAR2 Returns the text of the last error returned by the FileUpload. The result of this function is useful after GetStatus returns FileUploader.Failed or after the exception FileUploaderEx is raised.
EventHandler (EventName in VARCHAR2, EventData in PARAMLIST);

Handles all of the messages (events) from the bean. Should be called from the WHEN-CUSTOM-ITEM-EVENT trigger attached to the Bean Area.

  • EventName should be passed :SYSTEM.CUSTOM_ITEM_EVENT
  • EventData should be passed :SYSTEM.CUSTOM_ITEM_EVENT_PARAMETERS

Exceptions in the FileUploader package

Exception Purpose
FileUploaderEx

Exception raised when an unexpected error occurs in the FileUpload process.

When this exception is raised you should check the value of FileUploader.getError;

Utility Functions in the FileUploader package

The following functions are used to control various aspects of FileUpload functionality.

Function Purpose
GetSourceFile return VARCHAR2

Returns the name of the last file to be uploaded.

Note: this is the name of the file on the client. The upload process may have renamed the file when saving on the server if that was requested.

GetSourceDir return VARCHAR2

Returns the name of the directory that the last file was uploaded from.

GetSourceLen return PLS_INTEGER

Returns the size in bytes of the last file that was uploaded.

SetCompressed (CompressionOn in BOOLEAN)

Takes a boolean value to switch compression on or off. When compression is switched on, the FileUpload utility will automatically compress the file before uploading it. The file will be decompressed as it is written to the server.

Compressing the file in this way can vastly reduce the amount of time required for upload and is switched on by default. However, with certain file types such as files which are already compressed (.ZIP, .CAB files etc.) compression will actually slow down the overall upload process. To evaluate the effectiveness of the compression, switch Debug mode on (see below) and you will see the effect of compression on the number of bytes being uploaded.

SetDebug (DebugOn in BOOLEAN)

Takes a boolean value to switch Debug mode on. When Debug mode is on, various informational messages will be written to the Java console as the upload process progresses.

SetDialogPos (X_Pos in PLS_INTEGER,Y_Pos in PLS_INTEGER) Allows you to control the position of the file selection dialog in Pixels. (See Known Restrictions)

Making changes to the File Upload Utility

The FileUpload utility is provided with full source code and JavaDoc. The source code for the client and server parts of the code can be found in FileUpload\src.  If you do change the code you must remember to re-sign the uploadclient jar file with your own certificate.

Known Restrictions

At the time of publication the FileUpload utility has the following restrictions:

  1. No signed CAB file is shipped with the utility. For the UploadClient bean, we only ship a JAR file and a Signed JAR file. If you want to use the utility with native Internet Explorer (without JInitiator), you will have to create a signed CAB file of your own containing the classes in oracle.forms.demos.uploadclient using the makecab utility from Microsoft. Alternatively you can alter your baseie.htm file to replace the CABBASE parameter with ARCHIVE and refer to the supplied JAR files. If you do this, however, you will have to change your security settings in IE to allow allow unsigned content to run.
  2. File Sizes. Testing of the upload utility has only been carried out with files up to 7MBytes in size. Files that are uploaded are held completely in memory and the maximum size that can be transferred is dependent on the memory available to the JVM.
  3. The look and feel of the progress bar and file selection dialogs are not configurable and may not match the current look and feel being used by your application.
  4. Only one upload bean item is supported per Form
  5. The FileUpload.pll library is not designed for shared use e.g. the use of OPEN_FORM() with SHARE_LIBRARY_DATA. If you have multiple forms with the fileupload code which are sharing libraries, copy the FileUpload package into each of the Forms. (The remaining packages may be shared)
  6. The Bean has no visible aspect and attempting to open a canvas containing the bean will fail. To work around this, open another canvas first than then use the poplist to switch to the canvas with the upload bean on it.