Hi all, I attach zips of diffs/new classes for Commons-fileupload-1.0 to support progress reporting and of diffs to turbine 2.3 head to implement these in turbine. The commons stuff has been submitted to commons-dev for consideration. If successful with commons then perhaps you would consider my changes for turbine.
I have shown myself as author of the UploadTool class, but not added my
name elsewhere. No doubt you will let me know if i should.
One issue to consider, if it takes an appreciable amount of time to save
the fileitems after the request has been parsed, the progress box will
complete and close before the fileitems are saved and the response is
returned to the browser. This may leave the user wondering what
happened. I have considered not removing the Progress Reporter in the
ParameterParser, after completion of parsing the request, but leaving it
to the programmer to remove it after his upload processing and saving is
done. The cache should clear itself after the expiry period and leave
things clean if the programmer forgets.
What do you think?
Regards,
Peter
Following is the start of a HowTo.
Changes to classes
1. Commons now includes a FileUploadProgressReporter interface and a
DefaultFileUploadProgressReporter implementation.
2. A new UploadTool providing methods to create, cache and obtain a
reference to an object implementing the FileUploadProgressReporter
interface, and to query that instance for the progress info.
3. Changes to DefaultParameterParser to instruct it to obtain the
specified instance of the FileUploadProgressReporter if progress
reporting is required and pass this to the UploadService.
Setup
TurbineResources.properties
# add the UploadTool to request scoped pull tools
tool.request.upload=com.org.apache.turbine.util.upload.UploadTool
# cache timeout after which the object will be expired
# Added for upload progress reporting
# default to 10mins * 60secs * 1000millisecs (10 minutes)
UploadServiceCacheExpires=600000
# specify the Progress Reporter to use.
UploadServiceProgressReporter=org.apache.commons.fileupload.DefaultFileUploadProgressReporter
How it works
In your upload.vm page which includes your upload form, you first need
to create and obtain a reference to a specific instance of an object
implementing the FileUploadProgressReporter interface. This
is done by calling the getProgressReporterID() method of the UploadTool.
This method uses the uniqueid service to generate an ID, obtains an
instance of the FileUploadProgressReporter and caches it in the
TurbineGlobalCache, using the ID as a key, before returning the ID.
Use the getKeyParameterName() method of the UploadTool to get the
parameter name by which the ParameterParser will expect the ID to be
sent.
Add this to the <FORM tag as in the example Upload.vm below.
Note that I believe that this info must be sent before the files, so
should be included as addQueryData() as shown. It may work as a hidden
field sent before the files but I haven't tested this.
Add an onClick handler to the submit button which opens a new window to
display the UploadProgress.vm screen. (see example)
Be sure to add the ID to the path so that the UploadProgress screen can
retrieve the ID. This is done with
.addPathInfo("key", $key) in the Upload.vm Example
The UploadProgress.vm screen needs to ensure that the ID key passed to
it is available in the context. I do this by adding the following to the
doBuildTemplate() method of UploadProgress.java. I also set a
LayoutTemplate for the screen.
String key = data.getParameters().getString("key");
if (key != null)
{
context.put("key", key);
}
data.setLayoutTemplate("/ProgressLayout.vm");
In UploadProgress.vm I use the key parameter to pass to the UploadTool
so that it can query the correct instance of the ProgressReporter for
the Progress report. The window is set to reload every 5 seconds and to
close if the UploadTool finds that the requested instance of the
ProgressReporter has been removed from the cache. This happens when the
upload is completed. If the size of the request is 0, then the
connection has not yet been made and a please wait message can be
displayed.
On submission of the form the DefaultParameterParser checks for a
request parameter name equal to that set in the UploadTool. If it finds
it and a content-type header starting with 'multipart/form-data' it
reads the ID from the parameter and obtains the corresponding Progress
Reporter instance from the global cache. It then passes this instance to
the UploadService to parse the request.
On completion of the upload the Progress Reporter is removed from the
cache to leave things clean.
Finally, if the upload is interrupted and if for any reason the
ProgressReporter is orphaned in the cache, the cache service itself will
clean up on expiry of the timeout.
Notes :
If you are using a hidden _session_access_counter to prevent double
submission of forms then you should be aware that each refresh of the
UploadProgress.vm screen will increment the users counter and render the
counter check useless. To compensate for this call the
decrementSessionAccessCounter() method of UploadTool from your
UploadProgress.vm screen as shown in the example below.
You can provide an alternative implementation of a Progress Reporter by
changing the setting in TurbineResources.properties. This will allow you
to add such things as graphical displays to the progress report. You
will usually need to extend or replace the UploadTool to provide
suitable retrieval methods for the alternative class. Again this can be
specified in TurbineResources.properties.
EXAMPLE Upload.vm
#set ($key = $upload.getProgressReporterID())
#set ($keyparamname = $upload.getKeyParameterName())
<form method="post" enctype="multipart/form-data"
action="$link.setPage("Form.vm")
.setAction("Action")
.addQueryData($keyparamname, $key)">
<div align="center">
<table border="1">
<tr>
#fileUpload ("File" "file")
</tr>
<tr>
#fileUpload ("File2" "file2")
</tr>
</table>
<input type="image" name="eventSubmit_doUpload"
src="$ui.image($ui.uploadButton)"
onClick='window.open("$link.setPage("UploadProgress.vm")
.addPathInfo("key", $key)","status", "height=50,width=600");'/>
</form>
EXAMPLE UploadProgress.vm
$upload.decrementSessionAccessCounter()
#set ( $size = $upload.getRequestSize($key))
#set ( $file = $upload.getCurrentFile($key))
#set ( $read = $upload.getRequestBytesRead($key))
#if ($upload.inProgress($key) == false)
<SCRIPT>
window.close();
</SCRIPT>
#end
#if ($size.intValue() == 0)
Connecting, please wait ...
#else
<br />
Request size : $size
<br />
Reading File : $file
<br />
Processed : $read
#end
<SCRIPT>
window.setTimeout("window.location.reload()",5000);
</SCRIPT>
--
Peter Courcoux <[EMAIL PROTECTED]>
fileupload-pr.zip
Description: Zip archive
turbine-uploadprogress.zip
Description: Zip archive
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
