Asynchronous File Upload using Ajax, jQuery Progress Bar and Java

SHARE & COMMENT :

Introduction

In this tutorial you will learn about Asynchronous File Upload using Ajax, jQuery Progress Bar and Java

The image below shows a screenshot of the file upload that we are going to learn in this tutorial.

also read:

Let us see what all is needed to develop this application. We shall create a web application which has the following files.

  • FileUpload.html (The html/jsp file where the file upload happens)
  • jQuery related script files(We are going to discuss about this in detail later)
  • FileUploadListener.java(The listener file which listens to the file upload)
  • FileUploadListener.java (The servlet file which takes care of the upload process)
  • web.xml

The image below shows the screenshot of the file Structure. We have used netBeans IDE to develop the web Application.

File Structure

Let us try to understand the webstructure.We have a web folder which has FileUpload.html.The source packages has a java package “fileupload” which has two java files FileUploadListener.java and FileUploadServlet.java

There is another folder called “scripts” which has jquery.js which is used for the core javascript and Ajax features of jQuery library.
Apart from this we also have ui.core.js and ui.progressbar.js. These files are necessary for constructing a progress bar using jQuery.You can download the latest version of jQuery from Download jQuery

The jquery progress bar can be downloaded from Download jQuery UI

Now let us add in code into FileUpload.html
We shall be adding script , style and html body sections to the html files. Lets deal with each one of these sections one after the other.

Please find below the code for the html body section.

Html Body Code

<body>
		<center>
			<h2 class="backgroundClass">Sample File Upload</h2>
			<form id="myForm" enctype="multipart/form-data" method="post" target="uploadFrame" 
				action="example/FileUploadServlet" onsubmit="ajaxFunction()">
				<table border="1">
					<tr><td> <h4>File to be uploaded </h4></td><td>  <input type="file" name="txtFile" id="txtFile"		/></td></tr>
					<tr><td align="center" colspan="2">  <input type="submit" id="submitID" name="submit" value="Upload" /></td></tr>
				</table>
			</form>
			<div id="progressbarWrapper" style="height:20px;width:100px; ">
				<div id="progressbar" style="height:100%;"></div>
			</div>
			<br/>
			<div id="status" style="display:none">
				<table width="100%" class="backgroundClass">
					<tr>
					<td align="center" nowrap="nowrap">
						<div id="percentDone" style="font-weight: bold;"> </span>
					</td>
					</tr>
				</table>	
				<table width="100%" class="backgroundClass">
					<tr>
					<td align="center" nowrap="nowrap">
						<div id="bytesRead" style="font-weight: bold;"> </span>
					</td>
					</tr>
				</table>	
				<table width="100%" class="backgroundClass">
					<tr>
					<td align="center" nowrap="nowrap">
						<div id="totalNoOfBytes" style="font-weight: bold;"> </span>
					</td>
					</tr>
				</table>
			</div>
		</center>
		</body>

Script Code

Add the following code to the script section.
The script code pasted below will import the various script files necessary for jQuery core functions, progress bar and Ajax.
After importing, we need to do the following tasks:

  • Add the progressbar to the page(The progress bar will be hidden on the load of the page and will be shown only when the file upload begins.)
  • Make an Ajax request to the java Servlet(Servlet code will be discussed later).The Java Servlet will take care of the file upload on the server.
  • The ajaxFunction() will take care of sending the xmlHttpRequest.
  • funcReadyStateChange() will be invoked soon after getting the output.It takes care of the collecting the servlet output which is in the form of XML.funcReadyStateChange()will also take care of:
    • Parsing the response XML.
    • Updating the progress bar value through updateProgressbar() function
    • Update the page with the response.
  • The output xml will have details about the total number of bytes present in the file and the number of bytes uploaded.
  • Please note that the funcReadyState will make repetitive calls to ajaxFunction() and updateProgressBar() until the file is completely uploaded.Every request that is sent will get the recent most values of the “number of bytes that are uploaded” from the server.
<script src="scripts/jquery.js"></script>
	<script src="scripts/ui.core.js"></script>
	<script src="scripts/ui.progressbar.js"></script>
	<script src="scripts/ui.resizable.js"></script>
	<script>
		var progressBarValue=0;
		$(document).ready(function() {
			$( "#progressbar" ).progressbar({             value:0         });
			document.getElementById("progressbarWrapper").style.display = "none";
		});
        function updateProgressBar(progressBarValue)
        {
			$("#progressbar").progressbar("option","value",progressBarValue);
		}
        var req;

        function ajaxFunction(){
			var url = "example/FileUploadServlet";
            
            if (window.XMLHttpRequest){ 
				req = new XMLHttpRequest();
                try{
					req.onreadystatechange = funcReadyStateChange;
                    req.open("GET", url, true);
                } catch (e) {
					alert(e);
                }
                req.send(null);
            }

            else if (window.ActiveXObject) { 
				req = new ActiveXObject("Microsoft.XMLHTTP");
                if (req) {
					req.onreadystatechange = funcReadyStateChange;
                    req.open("GET", url, true);
                    req.send();
                }
            }
        }
             
        function funcReadyStateChange(){
			if (req.readyState == 4){
				if (req.status == 200){
					var xml = req.responseXML;
					var responseNode=xml.getElementsByTagName("response")[0];
					var noOfBytesRead =responseNode.getElementsByTagName("bytes_read")[0].
						childNodes[0].nodeValue;
					var totalNoOfBytes = responseNode.getElementsByTagName("content_length")[0].
						childNodes[0].nodeValue;
					progressBarValue=noOfBytesRead/totalNoOfBytes*100;             
					document.getElementById("status").style.display="block";
					document.getElementById("percentDone").innerHTML="Percentage Completed: "
						+Math.floor(progressBarValue)+"%";
					document.getElementById("bytesRead").innerHTML= "Number Of Bytes Read: "+
						noOfBytesRead;
					document.getElementById("totalNoOfBytes").innerHTML= "Total Number Of Bytes: "+
						totalNoOfBytes;
					document.getElementById("progressbarWrapper").style.display = "block";
                        
                    if (progressBarValue<100){
						window.setTimeout("ajaxFunction();", 100);
                        window.setTimeout("updateProgressBar(progressBarValue);", 100);
                           
                    } else {
                        alert("Done");
                        window.setTimeout("updateProgressBar(100);", 100);
                        document.getElementById("progressbarWrapper").style.display = "none";
                        document.getElementById("status").style.display="none";
                    }
				} else {
					alert(req.statusText);
				}
            }
        }
	</script>

Style Code

Now add the following code to the style section.

<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css" 
		rel="stylesheet" type="text/css"/> 
		<link href="style/ui.all.css" rel="stylesheet" type="text/css"/> 
		<link href="style/ui.core.css" rel="stylesheet" type="text/css"/> 
		<link href="style/ui.progressbar.css" rel="stylesheet" type="text/css"/> 
		<style type="text/css">
			.ui-progressbar-value { background-image: url(images/progressBarImage.jpg); }
			.backgroundClass
			{
				background-image: url(images/background.jpg);
				color:white;
			}
		</style>

Listener Code

This listener will listen to the event of file upload and has a method called fileUpdate() which will be automatically invoked as and when there is an update on fileUpload.

package fileupload;
	import org.apache.commons.fileupload.ProgressListener;
	public class FileUploadListener implements ProgressListener{
		private volatile long bytesRead = 0L, contentLength = 0L, item = 0L;   
		public FileUploadListener() {
			super();
		}

		public void update(long aBytesRead, long aContentLength, int anItem) {
			bytesRead = aBytesRead;
			contentLength = aContentLength;
			item = anItem;
		}

		public long getBytesRead() {
			return bytesRead;
		}

		public long getContentLength() {
			return contentLength;
		}
	
		public long getItem() {
			return item;
		}
	}

Servlet Code

The servlet will get the information about the number of bytes read through the listener and will construct a response xml with tags “bytes-read” and “content-length” etc.

package fileupload;
	
	import javax.servlet.Servlet;
	import javax.servlet.http.HttpServlet;
	import java.io.*;
	import java.util.*;
	import javax.servlet.http.*;
	import org.apache.commons.fileupload.*;
	import javax.servlet.ServletException;
	import org.apache.commons.fileupload.disk.DiskFileItemFactory;
	import org.apache.commons.fileupload.servlet.ServletFileUpload;
	
	public class FileUploadServlet extends HttpServlet implements Servlet {
	
	    private static final long serialVersionUID = 2740693677625051632L;
	
	    public FileUploadServlet() {
	        super();
	    }

		protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	        PrintWriter out = response.getWriter();
		    HttpSession session = request.getSession();
	        FileUploadListener listener = null;
			StringBuffer buffy = new StringBuffer();
		    long bytesRead = 0, contentLength = 0;

	        if (session == null) {
	            return;
		    } else if (session != null) {
	            listener = (FileUploadListener) session.getAttribute("LISTENER");

		        if (listener == null) {
			        return;
	            } else {
		            bytesRead = listener.getBytesRead();
	                contentLength = listener.getContentLength();
		        }
	        }

		    response.setContentType("text/xml");
	
		    buffy.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n");
			buffy.append("<response>\n");
	        buffy.append("\t<bytes_read>" + bytesRead + "</bytes_read>\n");
	        buffy.append("\t<content_length>" + contentLength + "</content_length>\n");

	        if (bytesRead == contentLength) {
	            buffy.append("\t<finished />\n");
		        session.setAttribute("LISTENER", null);
	        } else {
		        long percentComplete = ((100 * bytesRead) / contentLength);
	            buffy.append("\t<percent_complete>" + percentComplete + "</percent_complete>\n");
		    }
	        buffy.append("</response>\n");
		    out.println(buffy.toString());
	        out.flush();
		    out.close();
	    }

		protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	        FileItemFactory factory = new DiskFileItemFactory();
		    ServletFileUpload upload = new ServletFileUpload(factory);
	        FileUploadListener listener = new FileUploadListener();
		    HttpSession session = request.getSession();
			session.setAttribute("LISTENER", listener);
	        upload.setProgressListener(listener);
		    List uploadedItems = null;
			FileItem fileItem = null;
	        String filePath = "c:\\temp";

		    try {
			    uploadedItems = upload.parseRequest(request);
	            Iterator i = uploadedItems.iterator();
	
		        while (i.hasNext()) {
			        fileItem = (FileItem) i.next();
				    if (fileItem.isFormField() == false) {
					    if (fileItem.getSize() > 0) {
						    File uploadedFile = null;
							String myFullFileName = fileItem.getName(), myFileName = "", slashType = (myFullFileName.lastIndexOf("\\") > 0) ? "\\" : "/";
	                        int startIndex = myFullFileName.lastIndexOf(slashType);
		                    myFileName = myFullFileName.substring(startIndex + 1, myFullFileName.length());
			                uploadedFile = new File(filePath, myFileName);
				            fileItem.write(uploadedFile);
					    }
	                }
		        }
			} catch (FileUploadException e) {
	            e.printStackTrace();
		    } catch (Exception e) {
			    e.printStackTrace();
	        }
		}
	}

web.xml

We need to declare the servlet and also the listener in web.xml.

<servlet>
		<servlet-name>UploadServlet </servlet-name>
		<servlet-class>fileupload.FileUploadServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>UploadServlet</servlet-name>
		<url-pattern>/example/FileUploadServlet</url-pattern>
	</servlet-mapping>
	<listener>
		<listener-class>fileupload.FileUploadListener</listener-class>
	</listener>

also read:

Conclusion

In this tutorial , we have seen how to upload a file when we have java on the server side.
We have also seen how to do the same using jQuery-Ajax and jQuery progress bar.

Comments

comments

About Krishna Srinivasan

He is Founder and Chief Editor of JavaBeat. He has more than 8+ years of experience on developing Web applications. He writes about Spring, DOJO, JSF, Hibernate and many other emerging technologies in this blog.

Comments

  1. Nice code but i think there is some problem with it because when we click on upload it open the servlet file in new tab. How to stop that..????

  2. sd

  3. Hi Vicky,

    Looks like author missed out a ifram line from the html code. Please find the code below. Place it above the tag.

  4. Livingstone says:

    Great article.
    But what is the name of the javascript file where the source code is written into this page ?
    Where I can find the two images you are talking about (background.jpg and progressBarImage.jpg) ?

  5. Wow Good Code… its working well for me… thank uuuu…

  6. Some times , Upload button may click two times. How to fix it ?

  7. Some times , Upload button may click two times. How to fix it ?

Speak Your Mind

*

Close
Please support the site
By clicking any of these buttons you help our site to get better