Returning a binary file from REST service

You might want to return a binary file such as image or pdf from a REST service, if thats the case then JAX-RS provides you with 3 options. I wanted to try those options to i did create a sample application, that you can download from here. I did create a HelloBinaryService.java file which is a resource class that has 3 methods in each of these methods i am reading a static image file from c:/temp and returning it

package com.webspherenotes.rest;

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

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.StreamingOutput;

@Path("/hellobinary")
public class HelloBinaryService {

  @GET
  @Path("/file")
  @Produces("image/png")
  public File getFile(){
    File samplePDF = new File("c:/temp/distributedmap.png");
    return samplePDF;
  }

  @GET
  @Path("/fileis")
  @Produces("image/png")
  public InputStream getFileInputStream()throws Exception{
    FileInputStream fileIs = new FileInputStream("c:/temp/distributedmap.png");
    return fileIs;
  }

  @GET
  @Path("/fileso")
  @Produces("image/png")
  public StreamingOutput getFileStreamingOutput() throws Exception{
    
    return new StreamingOutput() {
      
      @Override
      public void write(OutputStream outputStream) throws IOException,
          WebApplicationException {
        FileInputStream inputStream = new FileInputStream("c:/temp/distributedmap.png");
        int nextByte = 0;
        while((nextByte  = inputStream.read()) != -1 ){
          outputStream.write(nextByte);
        }
        outputStream.flush();
        outputStream.close();
        inputStream.close();
      }
    };
  }
  
}
The first and easiest option would be to return a object of java.io.File directly and the JAX-RS will figure out how to read the file and return binary content of the file, but you cannot use this option if your returning a file that is not stored on the file system. Second option would be to return object of InputStream, in that case the InputStream could be pointing to file on local system or file stored in database or something like that, in this case JAX-RS container will figure out how to return bytes from InputStream and return it The last option would be to return object of StreamingOutput, this gives you most flexibility in this case JAX-RS container will give you control at the time of writing body of the message, this is little more work for you since you have to take care of reading the bytes from InputStream and write into output stream but then you get chance to compress the content,....

9 comments:

  1. Do you know if, in the case of returning an InputStream, the InputStream is closed when all the data is read?

    ReplyDelete
  2. This depends on container implementation but i believe it should close the InputStream

    ReplyDelete
  3. I tried 3rd snippet by removing produce line. and im sending StreamingOutput object (it contains zip file data ) - - so iam getting follwing error... help me ASAP
    com.sun.jersey.api.client.ClientHandlerException: A message body reader for Java type, interface javax.ws.rs.core.StreamingOutput, and MIME media type, text/html, was not found

    ReplyDelete
  4. Hi Sunil,

    don't close the OutputStream in your StreamingOutput example. See https://stackoverflow.com/questions/39572872/closing-jax-rs-streamingoutputs-outputstream for more about this.

    Cheers,
    Thomas

    ReplyDelete
  5. A web application developed based on the bigcommerce developer concept will adopt the layout of the application.

    ReplyDelete
  6. Hi, this is really helpful content do check this to
    CPanel Migration
    Develope E-Commerce Store

    ReplyDelete