File Upload (Using Java and Commons Upload)

January 31, 2008

Form-based File upload in HTML is defined in RFC 1867. The enctype attribute of the form element in HTML specifies the content type of the data submitted to the server. The default encrypt type is application/x-www-form-urlencoded . This content type is not efficient for forms containing non-ASCII data, binary data or files. In such case, the encrypt type multipart/form-data is used. A typical HTML form for file upload looks like:

<form action="fileUploadServlet" enctype="multipart/form-data" method="post">;
<input name="file" type="file" />;
<input name="submit" type="submit" value="submit" />;
</form>

Once the form is submitted, the binary multipart form-data is available in the HttpServletRequest as an InputStream. The regular form data are not available as Parameter and request.getParameter(“submit”) will always return null. So for any data submitted, you will have to know the content and then retrieve the content by parsing through the stream:

InputStreamReader input = new InputStreamReader(request.getInputStream());
BufferedReader buffer = new BufferedReader(input);
String line="";
while(line=buffer.readLine()!=null) {
     System.out.println("Multipart data " + line );
}

You can write a parser yourself to analyze each multipart data from the stream and grab it as they apply to your application. There are some good ones already written. Apache has a Commons Fileupload Library, now let’s see how we can use it to upload files.

Using Commons Fileupload API:

First of all, download the commons-fileupload.jar and put in in your classpath. It has a dependency on commons-io.jar. So, download it and put it in the classpath too.Given a request object, using the API you can check if it is a multipart/form-data request.

ServletFileUpload.isMultipartContent(request);

Now you know whether the request is multipart request or not. You can choose to decide whether the uploaded item is retained in memory or written temporarily to a file on disk.

FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List items = upload.parseRequest(request);

(For portlets, you have PortletFileUpload class which works just like the ServletFileUpload.)The default constructor DiskFileItemFactory() used to create the factory writes the item to memory before processing it further. You can provide the constructor an integer threshold of file-size (in bytes above which files will be stored in disk in the given repository path, and below which they are retained in memory)and the repository path on the disk to create a factory.

DiskFileItemFactory factory = new DiskFileItemFactory(0, "/test");

You can also set different configuration options:

DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setSizeThreshold(1000);
factory.setRepository("/test");
ServletFileUpload fileUpload = new ServletFileUpload(factory);
fileUpload.setSizeMax(10000); // in bytes, -1 indicates no limit

Once you have the FileItems, you want to know which of the FileItems are regular form fields, and which of them are file uploads, and treat them accordingly.

Iterator iter = items.iterator();
while (iter.hasNext()) {
     FileItem item = (FileItem) iter.next();
     if (item.isFormField()) {
        //Now, process the regular form field
        String name = item.getFieldName();
        String value = item.getString();
     } else {
        //Process the fileItem
        String fileName = item.getName();
        String contentType = item.getContentType();
        boolean isInMemory = item.isInMemory();
     }
}

If the item is in memory, you can either get the file as an InputStream or as array of bytes or write the item to a file.

//You can now get the data by reading the stream
InputStream inputStream = item.getInputStream();
//Get the file in an array of bytes
byte[] fileInBytes = item.get();
 //Or, write the item to a file
item.write(new File("file.txt"));

If it is a DiskFileItem (meaning, temporarily stored in a given location on disk), you can get the File Object from the temporary storage on the disk. Once you have the handle to the file, you can do whatever you like with it.

File file = item.getStoreLocation();

These temporary files in the disk are deleted automatically once the corresponding File object is no longer used and garbage collected. At any point, if an exception occurs, or if the file is too big, or you are done possing the file, you should delete the FileItem when you no longer require it.

item.delete();

When you do, item.getName(), the file name returned depends on the browsers. Some browsers like (IE and Opera) return the original file name along with the whole path information, while others (Firefox) return only the file name. So you will have to strip off the unwanted part of the file name.

String fileName = "C:\upload\file.txt";
fileName.substring(fileName.lastIndexOf("\")+1);
String fileName1 = "/upload/file1.txt";
String fileName1.substring(fileName1.lastIndexOf("/")+1);

This is just the basics of uploading a file from a client machine to the server using the web browser. Now if the file is too big, it may take some time to upload. So you may want to update the user about the progress by creating a ProgressListener() class. Users can now upload file of all sorts which may contain some viruses. So the first thing you need to do on server side is to scan the file item and check for virus. Files which are held in memory are not seen by virus scanners. So the files have to be written to a disk temporarily and scanned for viruses before they are sent over to the permanent storage.

16 Comments on File Upload (Using Java and Commons Upload)

Respond | Trackback

  1. srinivas reddy says:

    this article is really helpful

  2. ramchandra says:

    It’s really usefull but i need upload & download pdf as well as other type file
    how can we upload & download in jsp code?
    will just send me soluntion to ramchandrasalunke@yahoo.co.in reply me as u get it

  3. sacharya says:

    Ramchandra,
    Provided that you are in a Java Servlet, in order to download a file, all you need to do is get a handle to the File and set the response parameters and stream the bytes. You can do something like this:

    //File to download
    String filePath ="/usr/download";
    String fileName ="test.pdf";
    
    // Find the content type
    String contentType = URLConnection.guessContentTypeFromName(fileName);
    // if content types is still unknown
    if (contentType == null) {
    	contentType = "application/octet-stream";
    }
    File file = new File(filePath, fileName);
    BufferedInputStream input = new BufferedInputStream(new   FileInputStream(file));
    int contentLength = input.available();
    
    // init servlet response
    response.setContentType(contentType);
    response.setHeader("Content-disposition", "attachment; filename="" + fileName + """);
    response.setContentLength(contentLength);
    ServletOutputStream output = response.getOutputStream();
    
    byte[] buf = new byte[4 * 1024]; // 4K buffer
    int bytesRead;
    while ((bytesRead = input.read(buf)) != -1) {
         output.write(buf, 0, bytesRead);
    }
    
    output.flush();
    input.close();
    output.close();
    
  4. Ash says:

    Is there a way to pass the upload file via the URL like ?fine=…

  5. sacharya says:

    You will have to send the data stream to the server and read the stream. Thats what multipart/form-data allows you to do, if you are using a HTML client.

  6. Ash says:

    Already using multipart/form-data. I want to upload file via URL for a java servlet.
    As of now doGet accepts the file and on click of Submit button the file is uploaded
    and controll transferred to doPost method which shows 2nd screen with upload Succes
    or Fail msg. My req is directly upload the file via URL and show the 2nd screen.

  7. Fadia says:

    Hello Sudarshan Acharya,
    thank you so much for the FileUpload example.It was very helpful .I used it.
    Please do you have any link on your web site that explains how to make a progress bar with the FileUpload example.I like your style you explain in details.

    Thank you so much.

  8. admin says:

    Faida,
    I haven’t written anything on displaying upload progress yet, but you can use the same Apache Commons FileUpload API and implement a Progress listener ( see http://commons.apache.org/fileupload/using.html), and do a regular poll using AJAX.

  9. Avinash says:

    Hi Sudarshan,

    Thanks for writing such a nice article.
    Can you suggest how to handle multipart/mixed content type?
    My requirement is such that request contains all type of data – plain text, form data and
    attached file which can be sent using content type multipart/mixed.
    How to handle this scenario using the commins-fileupload?

    Again thanks in advance.

  10. sagar says:

    hi sudarshan
    i am using the file type as well as other inout type in the form.
    when i am trying to acces th eother inout type from java coed it throws null pointer exception.
    can you please tell me how i should upload my file ?

  11. Nishith says:

    hi Sudarshan…
    Your code is very usefull to me. But if i want to encrypt the file while uploading and decrypt the file while downloading how can i do that using apache…
    Is it possible.

  12. blogger.chil says:

    very useful

  13. chintan patel says:

    hello sir ,

    in your source code in download file code i can use in my application which is commons file upload and download but unfortunately i can upload the file in proper way for example i can upload file xyz.java, it can properly work uploading file but when i am download the file it can not the download this file for .java formate. so can you give me some proper format which i can dowload the file which is upload is same .java file

    that is i can download any file which define .extension , i can download this file .extension

  14. chintan patel says:

    i can create a application in servlet & jsp. so to give me proper logic in servlet structure

  15. UmaMaheswaraRao says:

    Hi,

    We are getting a strange error, when ever some users upload PDF files generated using MS Word are getting corrupted, its not simulatable by all users, is there any reason for pdf files getting corrupted?

  16. mugesh says:

    Its very Useful buddy!!! my problem is , First of all i have uploaded a file (with the help of your code) and convert it to zip file in a separate location…Now i just want to download that zip file and unzip it .. can u please give some idea regarding this…Thanks in advance…..

Respond

Comments

Comments