AJAX file upload monitoring - monitor your file upload with DWR and commons-fileupload
Marius Hanganu
Monitoring your file upload using ajax is a must have for any web 2.0 application. There are already some good examples developed by prosson and carsonm.
The first one looks great, but it is VERY slow. Takes several minutes to upload a file of 40M on localhost on my Core Duo which is Unnaceptable.
Fortunately, the second has the right speed. Actually it has it all, being written with prototype. The version I’m posting on this entry is just a variation to the version posted on mission data blog, using DWR. You can download all sources and dependencies along with Intellij IDEA project here.
The mechanism is simple and works like this:
- upload request is made with a dummy target (an embedded invisible iframe)
- on the server side, the upload servlet starts monitoring the upload and sets some objects on the session
- on the client side, a request for checking progress is made shortly after the upload has been triggered
- using DWR this request goes to a DWR proxy on the server side which returns some statistics
- when the upload servlet finished the upload, it will signal this to the DWR proxy, so that the next request for progress will be the last one
To integrate this in your own application you must do the following:
1. In web.xml declare the upload servlet and the dwr servlet (if it’s not there already):
<servlet>
<servlet-name>UploadServlet</servlet-name>
<servlet-class>ro.tremend.upload.UploadServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>scriptCompressed</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>UploadServlet</servlet-name>
<url-pattern>/Upload</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
2. In dwr.xml declare your proxy and a converter for the status object returned to UI:
<create creator=”new” javascript=”uploadProxy”>
<param name=”class” value=”ro.tremend.upload.UploadProxy”/>
</create>
<convert converter=”bean” match=”ro.tremend.upload.UploadStatus”/>
3. In your jsp or html page add the following:
<iframe id=’target_upload’ name=’target_upload’ src=” style=’display: none’></iframe>
<form enctype=”multipart/form-data” name=”form” method=”post” action=”Upload” onsubmit=”return startUploadMonitoring();” target=”target_upload”>
File to upload: <input id=”importFile” name=”importFile” type=”file”> <br/>
<input id=”submitButton” type=”submit” value=”Upload”/>
</form>
<div id=”uploadStatus”>
<!– specify width on this uploadProgressBar, otherwise the progress indicator won’t move –>
<div id=”uploadProgressBar” style=”width:200px;”>
<div id=”uploadIndicator”></div>
</div>
<div id=”uploadPercentage”></div>
</div>
The iframe is used to swallow the response to the upload request. The form contains the upload fields and the button. The uploadStatus div will hold the progress monitor.
4. In the head section of your jsp or html you will have to add the following:
<style type=”text/css”>
#uploadStatus {
width: 230px;
}
#uploadProgressBar {
height: 14px;
border: 1px solid #BBB;
text-align: center;
display: inline;
float: left;
}
#uploadIndicator {
height: 10px;
position: relative;
margin: 1px;
padding: 1px;
background: #9DC0F4;
width: 0;
float: left;
}
#uploadPercentage {
width: 20px;
display: inline;
float: right;
}
</style>
<script type=’text/javascript’ src=”dwr/util.js”></script>
<script type=’text/javascript’ src=”dwr/engine.js”></script>
<script type=”text/javascript” src=”dwr/interface/uploadProxy.js”></script>
<script type=”text/javascript” language=”JavaScript”>
var updater = null;
function checkStatus() {
uploadProxy.getStatus(function(stat) {
if (stat.status == 2) {
updateProgressBar(100);
return;
}
if (stat.status == 3) {
alert(”An error has occured! ” + stat.message);
return;
}
if (stat.status == 4) {
alert(”An error has occured! ” + stat.message);
return;
}
// do something with the percentage (nice loading bar, simply show the percentage, etc)
updateProgressBar(stat.percentComplete);
window.setTimeout(”checkStatus()”, 500);
});
}
function updateProgressBar(percentage) {
// make sure you set the width style property for uploadProgressBar, otherwise progress.style.width won’t work
var progress = document.getElementById(”uploadProgressBar”);
var indicator = document.getElementById(”uploadIndicator”);
var maxWidth = parseIntWithPx(progress.style.width) - 4;
var width = percentage * maxWidth / 100;
indicator.style.width = width + “px”;
var perc = document.getElementById(”uploadPercentage”);
perc.innerHTML = percentage + “%”;
}
function parseIntWithPx(str) {
var strArray = str.split(”p”);
return parseInt(strArray[0]);
}
function startUploadMonitoring() {
window.setTimeout(”checkStatus()”, 500);
return true;
}
</script>
5. You can assign unique identifiers to the set of files you’re uploading. The UploadServlet will make sure when upload finished to make
all files available on the HttpSession object under the key you’ve specified. To do that you’ll have to:
a) add a new field inside the form:
<input type=”hidden” name=”uniqueFileIdentifier” value=”1234″/>
b) in your java code, you can retrieve the files uploaded like this:
List filesUploaded = (List) session.getAttribute(UploadServlet.FILES_UPLOADED);
This will return a list of FileItem objects (for more information check the commons file upload documentation).
Posted in HTML, Javascript, Java, General |

April 3rd, 2007 at 11:54 am
This looks like just what I need. I’ve got the first solution you link to in place at the moment but, like you said, it’s very slow. Quick demo of your version is a lot faster. Thanks!
April 5th, 2007 at 6:38 am
Could you provide a .war file?
I use Eclipse , and I can’t integrate your source in your own application correctly
April 6th, 2007 at 6:07 am
Hi Wing,
I uploaded the war file to http://blog.tremend.ro/wp-content/uploads/2007/02/upload/upload%20monitor.war .
May 25th, 2007 at 11:10 am
hi, i download the war file you provide, make no change,
i seems it dose not work with a javascript error: uploadProxy is undefined.
because i don’t familiar with DWR.
thanks a lot!
May 27th, 2007 at 1:40 pm
Hi Marius,
it is really a very gut one solution. But I have a little problem with the upload from a file that is bigger than 50MB. The first way I try to upload it gives me a trouble message. By the second, third and so on, it goes. I could not find the bug. I think it’s a initializing problem, but where?
Best Regards
Vladimir
July 6th, 2007 at 8:39 am
its indeed a good solution. before came across this solution i spent couple of sleepless nights finding/implementing good solution for progress bar may be because i use low level API(multipartStream) to upload files. but I got lots of help from this article.
only thing i need to know how secure DWR is ? or what things we need to care while configuring DWR for secure web application.
September 26th, 2007 at 10:19 am
Hi,
Please help me in locating the file ‘dwr/interface/uploadProxy.js’. I am not able to run the application without this file and getting error. This file is not present in the ‘war’ file attached. Gembin had earlier pointed out this error “javascript error: uploadProxy is undefined”.
Thanks & Regards,
Abhishek
September 26th, 2007 at 10:36 am
Abhishek - please download the war from http://blog.tremend.ro/wp-content/uploads/2007/02/upload/upload%20monitor.war. When deploying it in a brand new tomcat - it works fine. You’ll get an error first time when doing the upload - will have to fix it - but after that it works fine.
You can find the uploadProxy.js at http://localhost:8080/upload%20monitor/dwr/interface/uploadProxy.js .
September 26th, 2007 at 6:24 pm
Thanks, but i’m not getting the file uploadProxy.js at the path given by you …
You hv said that “get an error first time when doing the upload - will have to fix it ” …. but how do I fix it for the first time ?
Thanks & Regards,
Abhishek
September 26th, 2007 at 6:29 pm
Hmm… I’ll have to post a new war + sources with this problem fixed. Check this blog later for an update.
October 25th, 2007 at 11:09 pm
serving up the uploadProxy.js from YOUR localhost doesn’t do the rest of us any good. Any chance you could post a better url?
November 29th, 2007 at 8:27 pm
thank you very very good .war
But i i’m getting an error with very large file (more than 2 gigas).
Is anybody have an idea ?
December 5th, 2007 at 2:13 pm
Hi,
can you provide me the file..
uploadProxy.js