File Upload Example Using RESTful Web Service with JAX-RS and Jersey

File Upload Example Using RESTful Web Service with JAX-RS and Jersey

In this example we are going to develop file upload capability using RESTful web service using JAX-RS and Jersey. As you will see, uploading a File using Jersey is pretty straight forward as it uses HTTP POST with the encoding type of multipart/form-data for the file operations.

Our sample HTML form is incredibly simple, having only only one input field of type file. Since the form contains a file input control, the enctype attribute should be specified as multipart/form-data, which dictates that the form will be sent as a multipart MIME message.

Getting Started

In order to run this tutorial yourself, you will need the following:

  • Java JDK 1.6 or greater
  • Favorite IDE Spring Tool Suite (STS), Eclipse IDE or NetBeans (I happen to be using STS because it comes with a Tomcat server built-in)
  • Tomcat 7 or greater or other popular container (Weblogic, Websphere, Glassfish, JBoss, VMWare vFabric, etc). For this tutorial I am using VMware vFabric tc Server Developer Edition which is essentially an enhanced Tomcat instance integrated with Spring STS
  • Jersey JAX-RS
  • log4J (for logging purposes)

Required Libraries

Copy all of the following jars to WebContent->WEB-INF->lib folder.

asm-3.1.jar
jersey-client-1.18.jar
jersey-core-1.18.jar
jersey-json-1.18.jar
jersey-multipart-1.18.jar
jersey-server-1.18.jar
jersey-servlet-1.18.jar
jsr311-api-1.1.1.jar
log4j-1.2.17.jar
mimepull-1.6.jar

Complete Project Overview

I have added the project overview to give you a full view of the structure and show you all files contained in this sample project.

jax-rs upload project structure

RESTful Web Service End Points

This main REST API example will accept the multipart/form-data data format.

#URIMethodDescription
1/rest/files/versionGETReturns version # of application (dummy method I use to ensure web service is running)
2/rest/files/uploadPOSTUses multipart/form-data encoding type. Because of this no characters are encoded. This value is required when you are using forms that have a file upload feature as you do not want to alter the binary files in any way.

Implement our File Upload Service Class using the JAX-RS API

Implementing a RESTful service requires nothing more than creating a POJO and annotating using the javax.ws.rs.* annotations. Additionally, you will need to ensure your class is under the package you defined in your web descriptor as Jersey will use this package to scan your classes for the existence RESTful resources.

upload url structure

Our upload method takes two parameters @FormDataParam. One of the @FormDataParam provides an InputStream to the file being uploaded and the other @FormDataParam provides content disposition header by using the FormDataContentDisposition object in the Jersey API.

package com.avaldes;

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

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

import com.sun.jersey.multipart.FormDataParam;

import org.apache.log4j.Logger;

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

@Path("/files")
public class RestFileUploadExample {
  static Logger logger = Logger.getLogger(RestFileUploadExample.class);
  private static final String api_version = "1.01A rev.10023";
  private static final String SAVE_FOLDER = "c://tmp/";
  
  @Path("/version")
  @GET
  @Produces(MediaType.TEXT_HTML)
  public String returnVersion() {
    return "<p>Version: " + api_version + "</p>";
  }
  
  @POST
  @Path("/upload")
  @Consumes(MediaType.MULTIPART_FORM_DATA)
  @Produces("text/html")
  public Response uploadFile(
      @FormDataParam("file") InputStream fileInputString,
      @FormDataParam("file") FormDataContentDisposition fileInputDetails) {
 
    String fileLocation = SAVE_FOLDER + fileInputDetails.getFileName();
    String status = null;
    NumberFormat myFormat = NumberFormat.getInstance();
    myFormat.setGroupingUsed(true);
    
    // Save the file 
    try {
     OutputStream out = new FileOutputStream(new File(fileLocation));
     byte[] buffer = new byte[1024];
     int bytes = 0;
     long file_size = 0; 
     while ((bytes = fileInputString.read(buffer)) != -1) {
      out.write(buffer, 0, bytes);
      file_size += bytes;
     }
     out.flush();  
     out.close();
            
     logger.info(String.format("Inside uploadFile==> fileName: %s,  fileSize: %s", 
          fileInputDetails.getFileName(), myFormat.format(file_size)));
            
     status = "File has been uploaded to:" + fileLocation 
                 + ", size: " + myFormat.format(file_size) + " bytes";
    } catch (IOException ex) {
      logger.error("Unable to save file: "  + fileLocation);
      ex.printStackTrace();
    }

    return Response.status(200).entity(status).build();
  }
}

Examining an HTTP request with multipart/form-data

The format of a multipart MIME message looks like:

 
 POST /RestfulFileUploadExample/rest/files/upload HTTP/1.1
 Host: localhost:8080
 Accept: */*
 Cache-Control: no-cache

 ----WebKitFormBoundaryE19zNvXGzXaLvS5C
 Content-Disposition: form-data; name="file"; filename="java_jaxrs_upload.png"
 Content-Type: image/png

 ----WebKitFormBoundaryE19zNvXGzXaLvS5C

Simple HTML Web Page (index.html)

There ins’t much to this html page, apart from the fact that you need to ensure that you add the encoding type as enctype=”multipart/form-data” in the HTML form element.

<h1>RESTful Web Service - File Upload Example</h1>  
<form action="/RestfulFileUploadExample/rest/files/upload" method="post" 
                                               enctype="multipart/form-data">  
 <p>  
   Select a file to Upload to server: <input type="file" name="file" size="60" />  
 </p>  
 <input type="submit" value="Upload File" />  
</form>  

Web Deployment Descriptor (web.xml)

This is a pretty straight forward deployment descriptor file – only thing you need to add is the location of you java package in the Jersey ServletContainer entry as init-param. Please ensure you add it to the web.xml file as shown below.

<?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" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>com.omega.rest</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  
  <servlet>
 
   <servlet-name>Jersey REST Service</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.avaldes</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>Jersey REST Service</servlet-name>
    <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>
</web-app>

Testing out the File Upload via the Web Services

To test out the application, simply select a file by clicking on the Choose File button and click Open after you have selected file from dialog window. Then click on the Upload File button.

file upload page

Once the file gets processed by the server you will see the response come back with the name of the file you uploaded and the size of the file specified in bytes.

file upload submitted

Confirming our Results

I ran this test several times and uploaded a few images for testing purposes.

upload file test

Download the Code

That’s It!

I hope you enjoyed this tutorial. It was certainly a lot of fun putting it together and testing it out. Please continue to share the love and like us so that we can continue bringing you quality tutorials. Happy Coding!!!

java jaxrs upload

Please Share Us on Social Media

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Leave a Reply

Your email address will not be published. Required fields are marked *