FileEntry

You are viewing an old version (v. 43) of this page.
The latest version is v. 53, last edited on Nov 13, 2018 (view differences | )
<< View previous version | view page history | view next version >>

Overview

Since 2.0

The ace:fileEntry components allows end users to upload files to the server, for processing and storage by the application. It uses a special AJAX technique for allowing ICEfaces incremental page updates within HTML 4 compliant browsers. Files and other form elements are all uploaded and processed together in a single JSF lifecycle. Upload progress is shown by fileEntry itself, in the browser, with no need for application involvement or server coding. An indeterminate progress bar will be shown initially, and if ICEpush is enabled in the application, then an incrementing progress bar will be shown, when progress notifications are received.

See the ICEfaces Showcase Live Demo of this component, complete with source code.
The fileEntry component requires that a non-AJAX full form submit occur to upload the file contents. This is an HTML 4 requirement. It then intercepts this submit and employs it's own AJAX techniques to allow for a partial page update, instead of the typical full page update. It does not use XmlHttpRequest at any point. Because of this, no component may upload the files by doing an AJAX submit, but rather must do a standard full form submit. On its own, only h:commandButton, without any f:param(s), will use the proper mechanism to upload files. Other AJAX components may still do form submits, for their own processing, but the file contents will not be uploaded, as per the HTML 4 specification. In order to use another component to upload files, its onclick property must be overridden:
<h:commandLink value="Upload" onclick="var form=document.getElementById('example-form');form.onsubmit();form.submit();"/>

Getting Started

Servlet 3 Configuration

Since ICEfaces EE 3.3.0.GA_P02, ICEfaces 4.0

To use ace:fileEntry on Servlet 3 servers you must add the following special configurations to your application web.xml file:

1. Configure the web.xml schema for web-app 3.0 (instead of 2.5):

<web-app version="2.5"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

<!-- Uncomment the declaration below and comment out the declaration above 
     to support Servlet 3.0 configuration, which allows multi-part uploads with ace:fileEntry
     on certain applications servers such as WAS and Glassfish -->

<!--
<web-app version="3.0"
     xmlns="http://java.sun.com/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
     xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
-->

2. Add the multipart configuration:

<!-- Servlet declarations and mappings -->
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>

        <!-- Add the multi-part entry below to enable Servlet 3 servers to support ace:fileEntry -->

        <multipart-config>
            <max-file-size>52428800</max-file-size>
            <max-request-size>52428800</max-request-size>
            <file-size-threshold>0</file-size-threshold>
        </multipart-config>

    </servlet>
<html ... xmlns:ace="http://www.icefaces.org/icefaces/components">
......
<ace:fileEntry id="fileEntryComp"
               label="File Entry"
               relativePath="uploaded"
               fileEntryListener="#{fileEntryController.listener}"/>

Attributes

TagLib Documentation
This section covers attributes involved in the typical use-cases for this component. For reference, the complete taglib documentation for this component is available here.

results contains the results of the most recent file upload operation. If the form was submitted, and no files were selected, than the previous results would remain. The results are an instance of FileEntryResults, which encapsulates a list of FileInfo objects, each corresponding to an individual file that was attempted to be uploaded in the one form submit.

fileEntryListener is the mechanism by which application are notified that a file upload attempt has been made. Files may have failed uploading, due to restrictions set on uploads, or they may have succeeded. For both cases, the attempt triggers this listener. This is an example of a prototypical fileEntryListener:

import org.icefaces.component.fileentry.*;

public void listener(FileEntryEvent event) {
    FileEntry fileEntry = (FileEntry) event.getSource();
    FileEntryResults results = fileEntry.getResults();
    for (FileEntryResults.FileInfo fileInfo : results.getFiles()) {
        if (fileInfo.isSaved()) {
            // Process the file. Only save cloned copies of results or fileInfo
        }
    }
}

callback is the means of specifying a FileEntryCallback, which assumes control of receiving the uploaded file data, supplanting the built-in file-system saving mechanism. This is intended for scenarios where files should be processed in memory, written directly to a database, or over a socket. Any instance where writing the files to the file-system are undesirable. There is a tutorial, providing a code example.

With ICEfaces 3.0.0 there is a known issue with updating the FileEntryStatus for an upload, from within the callback.

immediate controls when in the JSF lifecycle the fileEntryListener will get invoked:

  • true:  fileEntryListener invoked at end of ApplyRequestValues phase
    • If the upload attempt failed, or a file succeeded uploading, but processing of it deemed the file invalid, then the form submission can be made invalid, and UpdateModel phase skipped, by calling FacesContext.validationFailed() in the fileEntryListener method.
    • If other input components need to be validated using the details or contents of the uploaded files, having immediate="true" would make the fileEntryListener be invoked earlier than the ProcessValidations phase for the input components.
    • If the form submit button's action or actionListener method needs make use of the details of contents of the uploaded files, having immediate="true" would make the fileEntryListener be invoked earlier than the InvokeApplication phase for the command component.
  • false:  fileEntryListener invoked before RenderResponse phase
    • If the fileEntryListener depends on the validation of input components, or the action or actionListener methods of command components, having immediate="false" would make the fileEntryListener be invoked later than everything else. But, unlike action and actionListener methods, which are invoked during InvokeApplication, and so will not execute if the form submission is invalid, fileEntryListener will always be invoked, as it is invoked in the before part of RenderResponse phase.

Default is "false".

immediateValidation controls when in the JSF lifecycle the maxTotalSize, maxFileSize, maxFileCount and required validation will occur, marking the form as invalid and calling renderResponse, if necessary.

  • true:  Validation done during ApplyRequestValues phase
  • false:  Validation done during ProcessValidations phase
    • If immediate="true", then immediateValidation can not be set to false, since that would make the fileEntryListener be called before validation has occurred, so immediateValidation will automatically return a value of true.

Default is "true".

absolutePath, relativePath, useSessionSubdir and useOriginalFilename together determine where the uploaded files will be stored on the server's file-system.

absolutePath, or alternatively relativePath, determine the root directory into which files will be stored. If absolutePath is specified, then it is interpreted as an absolute path into the file-system. As well, it takes precedence if relativePath is also specified, erroneously. If relativePath is specified, it is interpreted as a path within the application deployment directory. The default is for, the root in which files are saved, to be the application deployment directory.

useSessionSubdir and useOriginalFilename are used to keep different files, from different users, from colliding with each other, in the save root.

When useSessionSubdir="false", files uploaded from different sessions will all be jumbled together. The default, of useSessionSubdir="true", separated files of different sessions, each user's file remain separate, and each time a given user logs back in, their files are kept separate from their previous logins' files. This simplified application processing and cleanup of each session's files.

When useOriginalFilename="true", files are saved on the server's file-system using their file name from the user's file-system. This might simplify processing, but could also be a security risk. As well, collisions may occur, where if different versions of the same file are uploaded over time, or different files from different directories, but which share the same file name, are uploaded, then the last one uploaded will overwrite earlier uploaded ones. The default, of useOriginalFilename="false", saves the uploaded files onto the server's file-system using uniquely generated file names.

maxTotalSize, maxFileSize and maxFileCount allow for setting quota constraints on upload operations. They are evaluated and enforced for each individual form submit and upload. Subsequent form submit and uploads do not take into account previous ones.There are no default values, as there are no default constraints. If any of these constraints are not met, then the form will be marked invalid, UpdateModel and InvokeApplication phases will not run, and none of the form fields will be set into the application's beans. When a fileEntry component is configured to allow uploading of multiple files in a single form submit, maxTotalSize and maxFileCount become more relevant.

  • Individual files may have their sizes constrained by maxFileSize. If a file's size is greater than maxFilesSize, then it will fail uploading.
  • If an application is concerned with the total size of all uploaded files in the aggregate, then maxTotalSize may be used to constrain the total size of all the files together. As each file is processed in sequence, when the maxTotalSize has been exceeded, the current file, and all subsequent files, will fail uploading. The previously processed files, which met the constraint, will have succeeded uploading.
  • The maxFileCount constrains the number of files which may be uploaded in a single form submit by the one fileEntry component. As each file is processed in sequence, when the maxFileCount has been exceeded, the current file, and all subsequent files, will fail uploading. The previously processed files, which met the constraint, will have succeeded uploading.

required is used to specify that at least one file must be uploaded as part of the current form submit, for the form to be valid. If no file was uploaded, then the form will be marked invalid, UpdateModel and InvokeApplication phases will not run, and none of the form fields will be set into the application's beans.

The required property does not look into whether the uploaded files succeeded or not, just that any files were attempted to be uploaded. The other constraints, which can fail uploads, will themselves invalidate the form.

The criteria for required to invalidate the form is:

  • A full form submit, not using AJAX, occured
  • No files were uploaded by this fileEntry component
  • The required property is true, for this fileEntry component
  • This fileEntry component is executing in the lifecycle. For example:
    • The submitting component did not do a single submit
    • The submitting component did not have an f:ajax tag, which excluded the fileEntry component from executing
  • The submitting component did not do a partial submit. That disables required processing

ICEfaces 3.x

The client side component object is exposed through the global variable name specified in the widgetVar attribute.

ICEfaces 4+

The "multiple" attribute is now fully supported to enable the selection and upload of multiple files using a single ace:fileEntry component.

The "widgetVar" attribute on the ACE components has been removed in ICEfaces 4 and in its place a new "ice.ace.instance()" client JavaScript object lookup API has been introduced. The reason for this change is to enable lazy-initialization of the ACE component JavaScript objects to improve runtime performance and reduce browser memory use.

var widget = ice.ace.instance('frm:componentId);
The ice.ace.instance function requires the full client id of the component to be specified, such as "j_idt77:componentId" instead of just "componentId". To reduce the complexity of working with complete IDs with this function it may be preferable in some cases to use prependId="false" in the enclosing form (e.g. <h:form prependId="false">).
This component doesn't have a client-side API made specifically to be used by application developers. However, the component's internal methods and variables can be accessed in this way, including the underlying jQuery object and objects from underlying Javascript libraries (if applicable), and can be used for whatever purpose a developer might have in mind.

Overriding Default Button Labels

It is possible to override the ace:fileEntry button labels in the following way.

Step 1. Create a properties file somewhere in your classpath. For example, in the ICEfaces Showcase app, create a file named 'fileEntryMessages.properties' in the 'org.icefaces.samples.showcase.view.resources' package.

Step 2. Populate that file, defining values for the appropriate ace:fileEntry button labels keys. For example...

org.icefaces.ace.component.fileEntry.ADD_FILES = Custom Add Files
org.icefaces.ace.component.fileEntry.ADD_FILES_detail = Custom Add Files
org.icefaces.ace.component.fileEntry.START_UPLOAD = Custom Start Upload
org.icefaces.ace.component.fileEntry.START_UPLOAD_detail = Custom Start Upload
org.icefaces.ace.component.fileEntry.CANCEL_UPLOAD = Custom Cancel Upload
org.icefaces.ace.component.fileEntry.CANCEL_UPLOAD_detail = Custom Cancel Upload

It is advised to define the same value for the '_detail' keys when overriding the default values.

Step 3. In your application's faces-config.xml file, add a <message-bundle> tag under the <application> tag, containing the package and name of your custom messages files (without including the '.properties' file extension). For our example above, this would look as follows:

	<application>
		<message-bundle>
			org.icefaces.samples.showcase.view.resources.fileEntryMessages
		</message-bundle>
	</application>

ARIA support

The following ARIA roles are supported: button (when in multiple mode).

Additional Notes

What to expect when some files fail validation in a multiple file upload? When you try to upload multiple files and some of them are rejected because of size, type or any other validation rule, you can expect that the files that passed validation will be saved in the server, and the file entry listener will fire, and you'll be able to see what files were successfully uploaded and which weren't by examining the FileEntryResults.

CSS Classes

The following markup represents the basic HTML structure of the component and the CSS classes it uses.

<!-- Root container -->
<div class="ice-file-entry [user defined classes]" style="[user defined styles]">
	<div class="buttonbar">
		<div class="buttons">
			<!-- Add files button -->
			<span class="add-files ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary">
				<span class="ui-button-icon-primary ui-icon ui-icon-plusthick"></span>
				<span class="ui-button-text">
					<span>Add files</span>
				</span>
				<input type="file"/>
			</span>
			<!-- Start upload button -->
			<button class="start ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary" type="submit">
				<span class="ui-button-icon-primary ui-icon ui-icon-circle-arrow-e"></span>
				<span class="ui-button-text">Start upload</span>
			</button>
			<!-- Cancel upload button -->
			<button class="cancel ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-primary" type="button">
				<span class="ui-button-icon-primary ui-icon ui-icon-cancel"></span>
				<span class="ui-button-text">Cancel upload</span>
			</button>
		</div>
	</div>
	<!-- Progress bar -->
	<div class="inactive">
		<div class="ui-progressbar ui-widget ui-widget-content ui-corner-all">
			<div class="ui-progressbar-value ui-widget-header ui-corner-left ui-corner-right"></div>
		</div>
	</div>
	<!-- List of files to upload -->
	<div>
		<table class="multiple-select-table"></table>
	</div>
</div>

Known Issues

The following known issues exist:

  • h:commandButton can be used to upload the files, as well as other components when a custom onclick handler is used that calls form.onsubmit() and then form.submit(). Most components directly call an AJAX submit function that will submit the whole form except for the file contents, if the custom onclick handler is not used.
  • In ICEfaces EE 3.3 the user interface for selecting multiple files to all upload at once is not complete, so only single file uploading per fileEntry component is enabled for now ("multiple" attribute is not supported). To upload multiple files in a single upload operation, simply use multiple fileEntry components in the same form.
  • In ICEfaces 3.0.0, When using FileEntryResults.FileInfo.updateStatus(FileEntryStatus status, boolean invalidate) from within a FileEntryCallback, to mark the upload as succeeded or failed, giving false for the invalidate parameter will cause the JSF lifecycle to fail, due to it calling FacesContext.renderResponse() too early in the lifecycle. Instead, give false, and then call FacesContext.validationFailed(). Newer versions of ICEfaces only call FacesContext.validationFailed(), which then results in FacesContext.renderResponse() being called later, at the appropriate time.  This is not an issue for FileEntryResults.FileInfo.updateStatus(FileEntryStatus status, boolean invalidate, boolean deleteFile) being called from a fileEntryListener, as the listener is invoked later in the lifecycle anyway.
  • In some servers, like Glassfish 3.1.2.2 and Websphere 8+, it is necessary for this component to work to add a multipart configuration tag in the application's web.xml file, inside the faces servlet declaration. Here is an example of such configuration:
             <multipart-config>
                 <max-file-size>52428800</max-file-size>
                 <max-request-size>52428800</max-request-size>
                 <file-size-threshold>0</file-size-threshold>
             </multipart-config>
    

    Moreover, in order to support the above tag, the web.xml file must follow the Servlet 3.0 schema, so it is necessary to declare the 3.0 version and appropriate namespaces in the root node of the file. Here is an example:

    <web-app version="3.0"
             xmlns="http://java.sun.com/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
             xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.

© Copyright 2017 ICEsoft Technologies Canada Corp.