main website home
  • About this blog

    This blog features updates, opinions, and technical notes from Caucho engineers about Caucho products, the enterprise Java industry, and PHP. Caucho Technology is the creator of the Resin Application Server and the Quercus PHP in Java engine. A leader in Java performance since 1998, Caucho is a Sun JavaEE licensee with over 9000 customers worldwide.
  • Tags

    ajaxworld bam candi cdi cloud cluster comet configuration deploy devoxx eclipse ejb embedded flash flex google app engine hessian hmtp ioc java ee 6 javaone javazone jms messaging newsletter nyjug osgi php pomegranate quercus resin resin 4.0 REST servlet sfjug silicon valley code camp spring testing training tssjs watchdog webbeans web profile websockets wordpress
  • Meta

    • Register
    • Log in
    • Entries RSS
    • Comments RSS
    • WordPress.org
« Servlet 3.0 Tutorial: @WebListener, @WebServlet, @WebFilter and @WebInitParam
Resin REST adminstration interface »

Servlet 3.0 Tutorial: Uploading files

The Internet is becoming more and more about sharing data, and, uploading files had become nearly universal requirement for a web application. Prior to Servlet 3.0, implementing file upload successfully required external libraries or tedious input processing. Version 3.0 of the spec goes a long way towards providing us with a solution to the problem in a generic and portable way.

Servlet 3.0 introduces a new API to handle multipart/form-data submissions. Multipart/form-data is a content type used to submit files, non-ASCII and binary data.
The browser will submit data using multipart/form-data encoding when an HTML form specifies it as a value for its enctype attribute.

Form example:

<FORM action="/multipart-upload"
       enctype="multipart/form-data"
       method="POST">

   Submitter: <INPUT type="text" name="submitter">
   Upload File: <INPUT type="file" name="content">
   <INPUT type="submit" value="Submit">

</FORM>

When submitting a form, the browser will stream the content in, all parts combined, with each part representing a field of a form. Parts are named after the input elements and separated from each other with string delimiters named boundary. For easier visualization I’ll show what submitted data would look like:

POST /multipart-upload HTTP/1.0
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryroNMZtQ4wMWb0fgH
Content-Length: 1000

------WebKitFormBoundaryroNMZtQ4wMWb0fgH
Content-Disposition: form-data; name="submitter"

John Doe
------WebKitFormBoundaryroNMZtQ4wMWb0fgH
Content-Disposition: form-data; name="content"; filename="a.txt"
Content-Type: text/plain

Some Data

The new Servlet 3.0 API specifies an interface javax.servlet.http.Part for each submission part and javax.servlet.http.HttpServletRequest makes them accessible using two methods:

  • getParts()
  • getPart(String name)

Since parts are named, method getPart(String name) can be used to access a particular part. Alternatively, method getParts() which returns an Iterable<Part> can be used to get an Iterator over all the parts.

javax.servlet.http.Part is a really simple interface which provides methods allowing to introspect each part and get its name, size, content-type, query the headers submitted with a part, delete or write part out to a disk. The interface has a few attributes and it may be useful to show it inline in its entirety.

package javax.servlet.http;

public interface Part {
  public InputStream getInputStream()
    throws IOException;

  public String getContentType();

  public String getName();

  public long getSize();

  public void write(String fileName)
    throws IOException;

  public void delete()
    throws IOException;

  public String getHeader(String name);

  public Iterable<String> getHeaders(String name);

  public Iterable<String> getHeaderNames();
}

So a simple servlet that accepts and saves a file could look as following:

package qa;

import java.io.*;

import javax.servlet.*;
import javax.servlet.http.*;

public class MyServlet extends HttpServlet {
  public void service(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException {
    //get the "content" part and save it.
    req.getPart("content").write("/tmp/file.dat");
  }
}

Before Resin 4.0.7 methods getPart(String) and getParts() return null in default configuration. Add <multipart-form enable=”true”/> tag to WEB-INF/resin-web.xml to turn the new Servlet 3.0 feature on.

<web-app xmlns="http://caucho.com/ns/resin">
  <multipart-form enable="true"/>
</web-app>

A special explanation should be given to method delete(). When invoked the method will delete the underlying temporary file as well as the file that the data has been moved or copied to using method write(String), thus method delete() should only be used if it’s necessary to delete the temporary file. In this situation method write(…) would have been never called in the course of processing.

Note: Resin keeps track of temporary files associated with a request and deletes them when it completes serving the request.

@MultipartConfig annotation

The spec introduces a new @javax.servlet.annotation.MultipartConfig annotation that helps the container identify a Servlet as capable of handling multipart/form-data requests. When this annotation is present on a Servlet, the HttpServletRequest makes the parts available.

The annotation can be used to configure location where the container should store temporary files, legal size limits on the entire request and parts, and a threshold size that triggers use of permanent storage.

@MultipartConfig annotation declares the following attributes:

  • location
  • maxFileSize
  • maxRequestSize
  • fileSizeThreshold

Resin’s implementation for Part’s write(…) method attempts to move data instead of copying. As moving files requires source and target be on the same partition co-location of temporary files and target files may offer superior performance. If the data can not be moved it is copied.

Example below illustrates use of @MultipartConfig annotation.

package qa;

import java.io.*;

import javax.servlet.annotation.MultipartConfig;
import javax.servlet.*;
import javax.servlet.http.*;

@MultipartConfig(location="/data")
public class MyServlet extends HttpServlet {
  public void service(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException {
    //target directory and location are the same. The file is moved(not copied)
    req.getPart("content").write("/data/file.dat");
  }
}

Servlet 3.0 offers more interesting features and I will try to cover support for Asynchronous communication next.

Tags: multipart/form-data, MultipartConfig, Servlet 3.0, tutorial

This entry was posted on Thursday, October 22nd, 2009 at 10:53 pm and is filed under Engineering. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

One Response to “Servlet 3.0 Tutorial: Uploading files”

  1. subwiz Says:
    April 26th, 2010 at 12:35 pm

    Beautiful tutorial. Waiting for the Asynchronous communication tutorial :-)

Leave a Reply

You must be logged in to post a comment.


Caucho Technology is proudly powered by WordPress and Quercus®
Entries (RSS) and Comments (RSS).

  • HOME |
  • CONTACT US |
  • DOCUMENTATION |
  • BLOG |
  • WIKI 4 |
  • WIKI 3 |
  • Resin: Java Application Server
Copyright (c) 1998-2012 Caucho Technology, Inc. All rights reserved.
caucho® , resin® and quercus® are registered trademarks of Caucho Technology, Inc.
resin® is a cloud optimized, java® application server that supports the java ee webprofile ®