Sunday, February 24, 2013

Upload files using RESTful Webservice


We are going to learn to upload image file using RESTful web service. We will also try to save the image in database and will retrieve the uploaded image from database.


Apache CXF provides three different approach for uploading a file. MultipartBody, Attachment and File. In this post, we will be using MultipartBody object for uploading the image. We will also learn how to store an image in database and retrieve it back.

The whole request from the HTML form is represented by MultipartBody object. MultipartBody contains method like getAllAttachments()getRootAttachment() etc. to fetch the attachment and process it further for extracting the data.

To acheive multipart body upload , we will annotate our rest method with @Consumes(MediaType.MULTIPART_FORM_DATA), which indicates that this method will accept multipart data.
  @Consumes(MediaType.MULTIPART_FORM_DATA)
  @Path("uploadImage")
  public Response uploadImage(@Multipart("file") 
    MultipartBody p_attachment);

Note that we are using MultipartBody as parameter type which represents whole html form. So final REST interface will look like ;
UploadImageRest.java
package com.sarf.restservice;

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 org.apache.cxf.jaxrs.ext.multipart.Multipart;
import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;

@Path("/uploadimage-service/")
@Produces(MediaType.APPLICATION_JSON)
public interface UploadImageRest {

 @POST
 @Consumes(MediaType.MULTIPART_FORM_DATA)
 @Path("uploadImage")
 public Response uploadImage(@Multipart("file") 
               MultipartBody p_attachment);
}


We need to provide implementation class of for our rest interface. So in uploadImage() method, we are using MultipartBody object to extract the attachment  in form of InputStream using method getRootAttachment().
Note: We assume here that html form is uploading only one file input.

UploadImageRestImpl.java
package com.sarf.restservice;

import java.net.URI;
import java.util.UUID;
import javax.ws.rs.core.Response;
import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.sarf.dto.ImageEntityDTO;
import com.sarf.service.UploadImageService;

@Service
public class UploadImageRestImpl implements UploadImageRest {

 @Autowired
 private UploadImageService uploadImageService;

 public Response uploadImage(final MultipartBody multipart) {
 try {
      this.uploadImageService.uploadImage(
       multipart.getRootAttachment()
       .getDataHandler().getInputStream());
      
      return Response.ok(ResponseType.SUCCESS).build();

     }catch(final Exception e) {
   e.printStackTrace();
          return Response.ok(ResponseType.SERVER_ERROR).build();
     }
   }

}

To store image in to database, we are going to write service class and spring data JPA Repository as DAO. Spring data Jpa is explained in my previous post as "Spring data JPA".

As mentioned in below image, we will create a service class "UploadImageService" which will internally use Repository class "ImageEntityRepository" to persist image into database.



Before we start writing the code, we need to create table for storing the image object.
Here we got entity class
ImageEntity.java
package com.sarf.domain;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Table;

@Entity
@Table(name = "ImageEntity")
public class ImageEntity implements Serializable {

 private static final long serialVersionUID = 1L;

 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 @Column(name = "imageId")
 private int nImageId;

 @Lob
 @Column(name = "image")
 private byte[] image;

 public int getnImageId() {
  return nImageId;
 }

 public void setnImageId(final int p_nImageId) {
  nImageId = p_nImageId;
 }

 public byte[] getImage() {
  return image;
 }

 public void setImage(final byte[] p_image) {
  image = p_image;
 }
}
UploadImageService.java

package com.sarf.service;
import java.io.InputStream;
import com.sarf.dto.ImageEntityDTO;

public interface UploadImageService {
  public void uploadImage(InputStream image);
}


UploadImageServiceImpl.java
package com.sarf.service;

import java.io.InputStream;
import java.util.List;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import javax.imageio.ImageIO;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.sarf.domain.ImageEntity;
import com.sarf.dto.ImageEntityDTO;
import com.sarf.repository.ImageEntityRepository;
import com.sarf.util.MapperUtil;
import com.sarf.util.UploadUtil;

@Service("uploadImageService")
@Transactional
public class UploadImageServiceImpl implements UploadImageService {

 @Autowired
 ImageEntityRepository imageEntityRepository;

 /** {@inheritDoc} */
 public void uploadImage(final InputStream iSImage) {
   final ImageEntity e = new ImageEntity();
   final byte[] image = getImageByteArray(iSImage);
   e.setImage(image);
   this.imageEntityRepository.saveAndFlush(e);
 }
    /**
    This method is used to conver an InputStream into byte array
    */
    private byte[] getImageByteArray(final InputStream inputStream) {
     byte images[] = null;
   try{
       final BufferedImage image = ImageIO.read(inputStream);
            final ByteArrayOutputStream baos = new ByteArrayOutputStream();
       ImageIO.write(image, "jpeg", baos);
       images = baos.toByteArray();
      }catch (final Exception e) {
        e.printStackTrace();
    }
   return images;
 }

}

This is our Entity class used to persist image into database using hibernate.



ImageEntityRepository.java
package com.sarf.repository;

import java.util.List;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import com.sarf.domain.ImageEntity;

@Repository
public interface ImageEntityRepository extends
  JpaRepository&ltImageEntity, Integer&gt {
}


persistence.xml

appContext.xml

web.xml
index.jsp