Welcome Message

"The difference between a successful person and others is not a lack of strength,
not a lack of knowledge, but rather a lack in will."
-Vince Lombardi

June 1, 2009

File Upload using JSP

Today i am going to explain about a interesting problem, that i faced during the course of my project development.

I was trying to do a file upload using jsp from a client to  server. For this when i searched the net, i got many code, at last i managed to edit one such code and customized it to my requirement. Here is the below code snippet of the form, which is used to upload a file.

File Name: FileUploadForm.jsp

<FORM ENCTYPE="multipart/form-data" METHOD="post" name="main" action="FileUploadAction.jsp">
<br>
<tr>
<td align="right"><b>Choose the file To Upload:</b></td>
<td><INPUT NAME="F1" TYPE="file"></td>
</tr>
<tr>
<td>&nbsp;</td>
<td>
<INPUT TYPE="button" VALUE="Upload" onclick=uploadFile()>
</td>
</tr>
</FORM>

Below scriplet is the code of other file which does the file upload action to the server

File Name: FileUploadAction.jsp
<%
//to get the content type information from JSP Request Header
String contentType = request.getContentType();
//here we are checking the content type is not equal to Null and as well as the passed data from mulitpart/form-data is greater than or equal to 0
if ((contentType != null) && (contentType.indexOf("multipart/form-data") >= 0)) {
DataInputStream in = new DataInputStream(request.getInputStream());
//we are taking the length of Content type data
int formDataLength = request.getContentLength();
byte dataBytes[] = new byte[formDataLength];
int byteRead = 0;
int totalBytesRead = 0;
//this loop converting the uploaded file into byte code
while (totalBytesRead < formDataLength) {
byteRead = in.read(dataBytes, totalBytesRead, formDataLength);
totalBytesRead += byteRead;
}
String file = new String(dataBytes);

//for saving the file name
String saveFile = file.substring(file.indexOf("filename=\"") + 10);
saveFile = saveFile.substring(0, saveFile.indexOf("\n"));
saveFile = saveFile.substring(saveFile.lastIndexOf("\\") + 1,saveFile.indexOf("\""));

String timestamp = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss.S.").format(new Date());
saveFile = userId+timestamp+saveFile;
int lastIndex = contentType.lastIndexOf("=");
String boundary = contentType.substring(lastIndex + 1,contentType.length());
int pos;
//extracting the index of file
pos = file.indexOf("filename=\"");
pos = file.indexOf("\n", pos) + 1;
pos = file.indexOf("\n", pos) + 1;
pos = file.indexOf("\n", pos) + 1;

int boundaryLocation = file.indexOf(boundary, pos) - 4;
int startPos = ((file.substring(0, pos)).getBytes()).length;
int endPos = ((file.substring(0, boundaryLocation)).getBytes()).length;

// creating a new file with the same name and writing the content in new file
String fileName = request.getRealPath("")+"\\excelFiles\\"+saveFile;
FileOutputStream fileOut = new FileOutputStream(fileName);
fileOut.write(dataBytes, startPos, (endPos - startPos));
fileOut.flush();
fileOut.close();

%>

But there is a serious problem in the above code, it works fine in the windows, whereas in linux machines this code fails. When i went through the everyline of the code, the line of code which gives different output in linux is,

String file = new String(dataBytes);
The above line is used to convert the file data in bytes to String. The reason we are doing is to find the boundary location of the file, now lets dont go deep in to this, this is more about file parsing formats. You can read the RFC which explains about the formats and parsing the file data from a HTML. But the strange that i could see in the above line is for the same file uploaded the String variable file length varies in windows server and linux server. I am not able to imaging the reason behind this.

After a long fight with the code and searching in the internet, i happen to see the apache commons api's. This api is really cool and interesting. It does all the things that is required for parsing and reduces our load. FileUploadForm.jsp can be used the same. But i changes the code of FileUploadAction.jsp. Below is the code

File Name: FileUploadAction.jsp

<%@ page import="java.text.SimpleDateFormat" %>
<%@ page import="org.apache.commons.fileupload.FileItem" %>
<%@ page import="org.apache.commons.fileupload.FileUploadException" %>
<%@ page import="org.apache.commons.fileupload.disk.DiskFileItemFactory" %>
<%@ page import="org.apache.commons.fileupload.servlet.ServletFileUpload" %>

<%@ page import="java.io.*" %>
<%@ page import="java.util.*" %>
<%

if (ServletFileUpload.isMultipartContent(request)){
ServletFileUpload servletFileUpload = new ServletFileUpload(new DiskFileItemFactory());
List fileItemsList = null;
try {
fileItemsList = servletFileUpload.parseRequest(request);
} catch (FileUploadException e) {
System.err.println("inside uploadUpdateACtion while parsing Exception is ["+e.getMessage()+"]");
}

Iterator i = fileItemsList.iterator();
//String comment = ((FileItem)i.next()).getString();
FileItem fi = (FileItem)i.next();
// filename on the client
String fileName = fi.getName();

fileName = fileName.substring(fileName.lastIndexOf("\\")+1);

String timestamp = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss.S.").format(new Date());
String saveFile = userId+timestamp+fileName;
// write the file
try {
fi.write(new File(request.getRealPath("")+"/excelFiles", saveFile));
} catch (Exception e) {
System.err.println("inside uploadUpdateACtion while writing the uploded file Exception is ["+e.getMessage()+"]");
}

%>

For the above code to work we need two jars to be included in the classpath commons-fileupload-1.2.1.jar and commons-io-1.4.jar. Both the jars are available in the apache site. This code will work for all environments and platforms. It has lot of features to be explored by me.
Thanks for reading, Have a great day !!!!!!!!!!!!!!!!!!!!!!!!!!!

-Sudan