easy, elegant and effective code…

This is the example of server side code for uploading a file using Jersey RESTful service. Server consumes a “multipart/form-data” request and returns Response on completion.

If file uploads successfully on the server, response code OK(200) will be returned. In case of any error, response code INTERNAL_SERVER_ERROR(500) will be returned.

Java Class for Server Side Code

package com.crispCode.rest.upload;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import com.sun.jersey.core.header.FormDataContentDisposition;
import com.sun.jersey.multipart.FormDataParam;

@Path("/upload")
public class RESTFileUpload
{
	private static final String FILE_UPLOAD_PATH = "C:/WINDOWS/Temp";
	private static final int BUFFER_SIZE = 1024;

	@POST
	@Path("/file")
	@Consumes(MediaType.MULTIPART_FORM_DATA)
	public Response fileUpload(
	        @FormDataParam("file") InputStream uploadedInputStream,
	        @FormDataParam("file") FormDataContentDisposition fileInfo)
	        throws IOException
	{
		Response.Status respStatus = Response.Status.OK;

		if (fileInfo == null)
		{
			respStatus = Response.Status.INTERNAL_SERVER_ERROR;
		}
		else
		{
			final String fileName = fileInfo.getFileName();
			String uploadedFileLocation = FILE_UPLOAD_PATH + File.separator
			        + fileName;

			try
			{
				saveToDisc(uploadedInputStream, uploadedFileLocation);
			}
			catch (Exception e)
			{
				respStatus = Response.Status.INTERNAL_SERVER_ERROR;
				e.printStackTrace();
			}
		}

		return Response.status(respStatus).build();
	}

	// save uploaded file to the specified location
	private void saveToDisc(final InputStream fileInputStream,
	        final String fileUploadPath) throws IOException
	{

		final OutputStream out = new FileOutputStream(new File(fileUploadPath));
		int read = 0;
		byte[] bytes = new byte[BUFFER_SIZE];

		while ((read = fileInputStream.read(bytes)) != -1)
		{
			out.write(bytes, 0, read);
		}

		out.flush();
		out.close();
	}
}

Code Description

Line #26: Where the server consumes a “multipart/form-data” request.

Line #28-29: The part “file” is a file that is uploaded. This is processed as an InputStream. Additional informaiton about the file from the “Content-Disposition” header can be accessed by the parameter fileInfo.

Line #46: call the saveToDisc() method in which data is read from the input stream and written to a file at the specified location (‘C:/WINDOWS/Temp’ in this case).

Line #50: In case of any error in writing to disc, returned response code is set to INTERNAL_SERVER_ERROR.

Jersey Servlet dispatcher

You need to register Jersey as the servlet dispatcher for REST requests. For that, you need update the web.xml file as follows –

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">
	<display-name>RESTFileUpload</display-name>
	<servlet>
		<servlet-name>jersey-serlvet</servlet-name>
		<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
		<init-param>
			<param-name>com.sun.jersey.config.property.packages</param-name>
			<param-value>com.crispCode.rest.upload</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>jersey-serlvet</servlet-name>
		<url-pattern>/rest/*</url-pattern>
	</servlet-mapping>
</web-app>

Description

The init-param – “com.sun.jersey.config.property.package” defines in which package jersey will look for the web service classes. This property must point to your resources classes (‘com.crispCode.rest.upload’ in this case). The URL pattern defines part of the base URL your application will be placed. In this case URL of the wadl file (on deploying the application) will be like – ‘http://<SERVER&gt;:<PORT>/RESTFileUpload/rest/application.wadl’ and the contents of the file will look like –

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<application xmlns="http://wadl.dev.java.net/2009/02">
	<doc xmlns:jersey="http://jersey.java.net/" jersey:generatedBy="Jersey: 1.12 02/15/2012 05:30 PM" />
	<grammars />
	<resources base="http://localhost:8585/RESTFileUpload/rest/">
		<resource path="/upload">
			<resource path="/file">
				<method name="POST" id="fileUpload">
					<request>
						<representation mediaType="multipart/form-data" />
					</request>
					<response>
						<representation mediaType="*/*" />
					</response>
				</method>
			</resource>
		</resource>
	</resources>
</application>

Required Jar Files

Following is the list of jar files required for successful development and deployment –
asm-3.3.1.jar
jersey-bundle-1.12.jar
jersey-core-1.12.jar
jersey-multipart-1.12.jar
mimepull-1.3.jar (if this jar is not in the classpath, client always gets the response – (415) UNSUPPORTED_MEDIA_TYPE)

References
http://jersey.java.net/nonav/documentation/latest/index.html
http://jersey.java.net/nonav/apidocs/1.5/contribs/jersey-multipart/com/sun/jersey/multipart/FormDataParam.html

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: