About Me

My photo
Ernakulam, Kerala, India
I am Sajadh, author of this blog. I run this with loads of passion.
If you are into java, you may find lot of interesting things around ...
Advance thanks for your queries to sajadhaja90@gmail.com.

Thursday, 8 November 2012

ProgressBar for File Upload using the Dojo

This tutorial demonstrates how to use a DojoSW ProgressBar to display the progress of a file upload, utilizing JavaSW classes that we developed in other tutorials. An example of the Dojo ProgressBar is shown below:
Dojo ProgressBar Example
In another tutorial, we created a TestProgressListener class to allow us to monitor the progress of a file upload to a servletW. We utilized the ApacheSW Commons FileUploadS library to handle the file upload. The TestProgressListener class implements the ProgressListener interface from the FileUpload library. The file gets uploaded to the TestServlet class, which sticks a reference to the TestProgressListener in a session. The ProgressServlet reads the TestProgressListener object from the session and displays the status of the file upload. The upload form to upload files to the TestServlet is located on upload.jsp.
I downloaded the Dojo AjaxW library from http://dojotoolkit.org/. I unpacked the library and placed it in the web directory of my project. In a production system, I would place the library somewhere on a web server rather than actually packaging it into a project, but this is fine for demonstration purposes.
file-upload project I modified the upload.jsp file from the previous tutorial, to include the Dojo ProgressBar. I added a style section for CSSW formatting of the ProgressBar. The Dojo library is referenced via "dojo-release-1.0.2/dojo/dojo.js". The ProgressBar is included via the JavascriptW call to dojo.require("dijit.ProgressBar").

upload.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Upload Page</title>

<style type="text/css">
@import "dojo-release-1.0.2/dijit/themes/tundra/tundra.css";
@import "dojo-release-1.0.2/dojo/resources/dojo.css"
</style>

<script type="text/javascript" src="dojo-release-1.0.2/dojo/dojo.js" djConfig="parseOnLoad: true">
</script>

<script type="text/javascript">
dojo.require("dijit.ProgressBar");

function doProgress() {
 var button = window.document.getElementById("submitButton");
 button.disabled = true;
 var max = 100;
 var prog = 0;
 var counter = 0;
 getProgress();
 doProgressLoop(prog, max, counter);
}

function doProgressLoop(prog, max, counter) { 
    var x = dojo.byId('progress-content').innerHTML;
    var y = parseInt(x);
    if (!isNaN(y)) {
     prog = y;
    }
    jsProgress.update({ maximum: max, progress: prog });
 counter = counter + 1;
 dojo.byId('counter').innerHTML = counter;
    if (prog < 100) {
     setTimeout("getProgress()", 500);
     setTimeout("doProgressLoop(" + prog + "," + max + "," + counter + ")", 1000);
    }
}

function getProgress() {
    dojo.xhrGet({url: 'progress', // http://localhost:8080/file-upload/progress
                 load: function (data) { dojo.byId('progress-content').innerHTML = data; },
                 error: function (data) { dojo.byId('progress-content').innerHTML = "Error retrieving progress"; }
                });
}

</script>
</head>
<body>
<div>
 <form name="form1" id="form1" action="test" method="post" enctype="multipart/form-data">
 <input type="hidden" name="hiddenfield1" value="ok">
 Files to upload:
 <br/>
 <input type="file" size="50" name="file1">
 <br/>
 <input type="file" size="50" name="file2">
 <br/>
 <input type="file" size="50" name="file3">
 <br/>
 <input type="button" value="Upload" id="submitButton" onclick="form1.submit();doProgress();">
 </form>
</div> 
<div class="tundra">Progress: 
 <div dojoType="dijit.ProgressBar" style="width: 300px" jsId="jsProgress" id="downloadProgress">
 </div>
</div>

<br/><br/><br/>
<div style="visibility: visible">
Content from Progress Servlet: <span id="progress-content">---</span><br/>
Counter: <span id="counter">---</span><br/>
</div> 
</body>
</html>
Clicking the Upload button submits the form and calls the doProgress() function which disables the Upload button and initializes the max, prog, and counter variables. The max variable is the maximum progress, which is 100 (100%). The prog variable is the upload progress, which starts at 0 (0%). The counter variable is a simple counter variable. The getProgress() function is called and then the doProgressLoop() function is called.
The getProgress() function contacts the ProgressServlet (via the 'progress' URL) and puts the results in the 'progress-content' span element.
The doProgressLoop() is a recursive function that calls itself until the file upload is complete. It reads the 'progress-content' span element, which gets its innerHTML value from the ProgressServlet via the getProgress() call. If the 'progress-content' value is an integer, the prog (progress) variable is updated with this value. The ProgressBar (jsProgress) is updated with the current progress via the jsProgress.update call. The counter is incremented and its value is placed in the 'counter' span element. If the prog (progress) variable is less than 100, meaning that the file upload hasn't completed yet, then getProgress() is called in 500 milliseconds, and doProgressLoop() is called in 1000 milliseconds (1 second) with the current prog, max, and counter values.
The doProgressLoop() will continue to call itself until the progress is 100%, meaning that the file upload has completed. At this point, the TestServlet will display another page, since the upload will be complete.



The project's web.xmlW file is shown here. We have a TestServlet mapped to '/test' and a ProgressServlet mapped to '/progress'.

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="file-upload" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
 <servlet>
  <servlet-name>TestServlet</servlet-name>
  <servlet-class>test.TestServlet</servlet-class>
 </servlet>
 <servlet>
  <servlet-name>ProgressServlet</servlet-name>
  <servlet-class>test.ProgressServlet</servlet-class>
 </servlet>
 <servlet-mapping>
  <servlet-name>TestServlet</servlet-name>
  <url-pattern>/test</url-pattern>
 </servlet-mapping>
 <servlet-mapping>
  <servlet-name>ProgressServlet</servlet-name>
  <url-pattern>/progress</url-pattern>
 </servlet-mapping>
</web-app>
The TestServlet class is shown here. This is the class that handles the file upload. It creates a TestProgressListener to monitor the file upload and sticks this in the session.

TestServlet.java

package test;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class TestServlet extends HttpServlet {

 private static final long serialVersionUID = 1L;
// public static final long MAX_UPLOAD_IN_MEGS = 50;

 public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
  doPost(request, response);
 }

 public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
  response.setContentType("text/html");
  PrintWriter out = response.getWriter();
  
  out.println("Hello<br/>");

  boolean isMultipartContent = ServletFileUpload.isMultipartContent(request);
  if (!isMultipartContent) {
   out.println("You are not trying to upload<br/>");
   return;
  }
  out.println("You are trying to upload<br/>");

  FileItemFactory factory = new DiskFileItemFactory();
  ServletFileUpload upload = new ServletFileUpload(factory);
//  upload.setSizeMax(MAX_UPLOAD_IN_MEGS * 1024 * 1024);
  
  TestProgressListener testProgressListener = new TestProgressListener();
  upload.setProgressListener(testProgressListener);

  HttpSession session = request.getSession();
  session.setAttribute("testProgressListener", testProgressListener);
  
  try {
   List<FileItem> fields = upload.parseRequest(request);
   out.println("Number of fields: " + fields.size() + "<br/><br/>");
   Iterator<FileItem> it = fields.iterator();
   if (!it.hasNext()) {
    out.println("No fields found");
    return;
   }
   out.println("<table border=\"1\">");
   while (it.hasNext()) {
    out.println("<tr>");
    FileItem fileItem = it.next();
    boolean isFormField = fileItem.isFormField();
    if (isFormField) {
     out.println("<td>regular form field</td><td>FIELD NAME: " + fileItem.getFieldName() + 
       "<br/>STRING: " + fileItem.getString()
       );
     out.println("</td>");
    } else {
     out.println("<td>file form field</td><td>FIELD NAME: " + fileItem.getFieldName() +
//       "<br/>STRING: " + fileItem.getString() +
       "<br/>NAME: " + fileItem.getName() +
       "<br/>CONTENT TYPE: " + fileItem.getContentType() +
       "<br/>SIZE (BYTES): " + fileItem.getSize() +
       "<br/>TO STRING: " + fileItem.toString()
       );
     out.println("</td>");
    }
    out.println("</tr>");
   }
   out.println("</table>");
  } catch (FileUploadException e) {
   out.println("Error: " + e.getMessage());
   e.printStackTrace();
  }
 }
}
The TestProgressListener class allows us to monitor the progress of the file upload.

TestProgressListener.java

package test;

import org.apache.commons.fileupload.ProgressListener;

public class TestProgressListener implements ProgressListener {

 private long num100Ks = 0;

 private long theBytesRead = 0;
 private long theContentLength = -1;
 private int whichItem = 0;
 private int percentDone = 0;
 private boolean contentLengthKnown = false;

 public void update(long bytesRead, long contentLength, int items) {

  if (contentLength > -1) {
   contentLengthKnown = true;
  }
  theBytesRead = bytesRead;
  theContentLength = contentLength;
  whichItem = items;

  long nowNum100Ks = bytesRead / 100000;
  // Only run this code once every 100K
  if (nowNum100Ks > num100Ks) {
   num100Ks = nowNum100Ks;
   if (contentLengthKnown) {
    percentDone = (int) Math.round(100.00 * bytesRead / contentLength);
   }
   System.out.println(getMessage());
  }
 }

 public String getMessage() {
  if (theContentLength == -1) {
   return "" + theBytesRead + " of Unknown-Total bytes have been read.";
  } else {
   return "" + theBytesRead + " of " + theContentLength + " bytes have been read (" + percentDone + "% done).";
  }

 }

 public long getNum100Ks() {
  return num100Ks;
 }

 public void setNum100Ks(long num100Ks) {
  this.num100Ks = num100Ks;
 }

 public long getTheBytesRead() {
  return theBytesRead;
 }

 public void setTheBytesRead(long theBytesRead) {
  this.theBytesRead = theBytesRead;
 }

 public long getTheContentLength() {
  return theContentLength;
 }

 public void setTheContentLength(long theContentLength) {
  this.theContentLength = theContentLength;
 }

 public int getWhichItem() {
  return whichItem;
 }

 public void setWhichItem(int whichItem) {
  this.whichItem = whichItem;
 }

 public int getPercentDone() {
  return percentDone;
 }

 public void setPercentDone(int percentDone) {
  this.percentDone = percentDone;
 }

 public boolean isContentLengthKnown() {
  return contentLengthKnown;
 }

 public void setContentLengthKnown(boolean contentLengthKnown) {
  this.contentLengthKnown = contentLengthKnown;
 }

}
The ProgressServlet class gets the TestProgressListener reference from the session. In our earlier tutorial, we displayed a friendly status message using testProgressListener.getMessage(). Since now we just want to know the percentage done, we instead call testProgressListener.getPercentDone() and output this to the response.

ProgressServlet.java

package test;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class ProgressServlet extends HttpServlet {

 private static final long serialVersionUID = 1L;

 public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
  doPost(request, response);
 }

 public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
  response.setContentType("text/html");
  response.setHeader("Cache-Control", "no-cache");
  
  PrintWriter out = response.getWriter();

  HttpSession session = request.getSession(true);
  if (session == null) {
   out.println("Sorry, session is null"); // just to be safe
   return;
  }

  TestProgressListener testProgressListener = (TestProgressListener) session.getAttribute("testProgressListener");
  if (testProgressListener == null) {
   out.println("Progress listener is null");
   return;
  }

//  out.println(testProgressListener.getMessage());
  out.println(testProgressListener.getPercentDone());

 }
}
 
Now, let's see the ProgressBar in action. I started up the project. I browsed to the BigFile.mp3 and set this as the file to upload. I then clicked the Upload button.
File Upload Start As you can see, when the upload starts, the Upload button gets disabled. The progress is displayed on the DojoSW ProgressBar. Here, the upload is 22% complete. We can also see that this screen capture was taken after about 6 seconds.
File Upload Progress When the file upload is done, the TestServlet class displays some information about the upload.
File Upload Finished The Dojo ProgressBar is a very visually appealing way to display the status of a task. In this tutorial, we've seen how we can use it to display the status of a file upload.
 

1 comment:

  1. Reference :-- http://www.avajava.com/tutorials/lessons
    is a good tutorial for studying design patterns

    ReplyDelete

You can enter queries here...