This tutorial is a quick guide for handling files upload and download using REST Services. We will demonstrate how to upload a file using a Client API which will be received by a REST Service. In the second part of it we will show to download a file from a REST Service. Screencast included!

Uploading a file using a REST Service

In order to upload, we will be using some RESTEasy and Apache IO Utility classes. The core WS method is named "/upload" and consumes a multipart/form-data. Within this method we collect the File which will be named as "attachment" on the upload client. two utility methods are included:

  • getFileName: extracts the file name from the Header
  • writeFile: writes the file to disk
package com.mastertheboss;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

import javax.ws.rs.*;
import javax.ws.rs.core.*;

import org.apache.commons.io.IOUtils;
import org.jboss.resteasy.plugins.providers.multipart.InputPart;
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;

    @Path("/demo")
    public class RestFilesDemo  {
    @POST
    @Path("/upload")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response uploadFile(MultipartFormDataInput input) throws IOException {
        Map<String, List<InputPart>> uploadForm = input.getFormDataMap();
 
        // Get file data to save
        List<InputPart> inputParts = uploadForm.get("attachment");
 
        for (InputPart inputPart : inputParts) {
            try {
 
                MultivaluedMap<String, String> header = inputPart.getHeaders();
                String fileName = getFileName(header);
   
                // convert the uploaded file to inputstream
                InputStream inputStream = inputPart.getBody(InputStream.class,
                        null);
 
                byte[] bytes = IOUtils.toByteArray(inputStream);

		String path = System.getProperty("user.home") + File.separator + "uploads";
		File customDir = new File(path);

		if (!customDir.exists()) {
			customDir.mkdir();
	        }
                fileName = customDir.getCanonicalPath()  + File.separator + fileName;
                writeFile(bytes, fileName);
 
                  
                return Response.status(200).entity("Uploaded file name : " + fileName)
                        .build();
 
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }
 
    private String getFileName(MultivaluedMap<String, String> header) {
 
        String[] contentDisposition = header.getFirst("Content-Disposition").split(";");
 
        for (String filename : contentDisposition) {
            if ((filename.trim().startsWith("filename"))) {
 
                String[] name = filename.split("=");
 
                String finalFileName = name[1].trim().replaceAll("\"", "");
                return finalFileName;
            }
        }
        return "unknown";
    }
 
    // Utility method
    private void writeFile(byte[] content, String filename) throws IOException {
        File file = new File(filename);
	System.out.println("----->"+filename);
        if (!file.exists()) {
            file.createNewFile();
        }
        FileOutputStream fop = new FileOutputStream(file);
        fop.write(content);
        fop.flush();
        fop.close();
    }
}   

 And now the client side: at first we will use a simple HTML form with a file component in it:

<html>
   <head>
      <title>Start Page</title>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   </head>
   <body>
      <h1>REST Upload demo</h1>
      <form method="post" action="rest/demo/upload" enctype="multipart/form-data">
         <input type="hidden" name="action" value="upload" />
         <label>Load your file:</label>
         <input type="file" name="attachment" />
         <br />
         <input type="submit" value="Upload file" />
      </form>
   </body>
</html>

Please note that the file component name ("attachment") needs to match with the information extracted from the REST Service.

Here is the pom.xml which I have used to build and deploy the application:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.itbuzzpress</groupId>
    <artifactId>restupdownload</artifactId>
    <version>1.1</version>
    <packaging>war</packaging>

    <name>restupdownload</name>

    <properties>
        <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    
    <dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.wildfly.bom</groupId>
				<artifactId>wildfly-javaee7-with-tools</artifactId>
				<version>12.0.0.Final</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>

		</dependencies>
	</dependencyManagement>

	<dependencies>
		<dependency>
			<groupId>org.jboss.spec.javax.ws.rs</groupId>
			<artifactId>jboss-jaxrs-api_2.0_spec</artifactId>
			<scope>provided</scope>
		</dependency>


		<dependency>
			<groupId>org.jboss.resteasy</groupId>
			<artifactId>resteasy-multipart-provider</artifactId>
			<version>3.5.1.Final</version>
		</dependency>

		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>2.5</version>
		</dependency>
	</dependencies>

    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.wildfly.plugins</groupId>
                <artifactId>wildfly-maven-plugin</artifactId>
                <version>1.0.2.Final</version>
                <configuration>
                    <filename>${project.build.finalName}.war</filename>
                </configuration>
            </plugin>
            <plugin>														       
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                    <compilerArguments>
                        <endorseddirs>${endorsed.dir}</endorseddirs>
                    </compilerArguments>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
          
        </plugins>
    </build>

</project>

You can build and deploy with:

$ mvn clean install wildfly:deploy

Check the screencast to see how we deployed this project:

Now another example which uses Apache http utils package to send the file using a POST request:

package client;

import java.io.File;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.DefaultHttpClient;

public class RESTClient {
    
    public static void main(String args[]) throws Exception {
        File f = new File("/home/jboss/myfile.txt");
        sendFile(f);
    }
    public static void sendFile(File file) throws Exception 
    {
	String BASE_URL="http://localhost:8080/RESTDemo/rest/upload";
        HttpClient client = new DefaultHttpClient() ;
        HttpPost postRequest = new HttpPost (BASE_URL) ;
        try
        {
        	
            //Set various attributes 
            MultipartEntity multiPartEntity = new MultipartEntity () ;
           
           // multiPartEntity.addPart("fileName", new StringBody(file.getName() != null ? file.getName() : file.getName())) ;
  
            FileBody fileBody = new FileBody(file, "application/octect-stream") ;
            //Prepare payload
            multiPartEntity.addPart("attachment", fileBody) ;
  
            //Set to request body
            postRequest.setEntity(multiPartEntity) ;
             
            //Send request
            HttpResponse response = client.execute(postRequest) ;
             
            //Verify response if any
            if (response != null)
            {
                System.out.println(response.getStatusLine().getStatusCode());
            }
        }
        catch (Exception ex)
        {
            ex.printStackTrace() ;
        }
    }
}

Downloading a file using a REST Service

You can use REST Service as downloading mechanism as well. In this case, we will just require to wrap a file with the Response object and Producing the correct Stream for the client. Since we return a JAR file, it will be an APPLICATION_OCTET_STREAM:

@GET
@Path("/jar")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response downloadFile() {
	File file = new File("/home/user/Downloads/classes.jar");
	ResponseBuilder response = Response.ok((Object) file);
	response.header("Content-Disposition", "attachment;filename=classes.jar");
	return response.build();
}

Downloading the file from the Client side can be done with a variety of options. Here is my download client which I use to download a JAR class file:

public static void downloadUpdate() {
	String BASE_URL="http://localhost:8080/RESTDemo/rest/jar";

	Client client = ClientBuilder.newClient();

	
	try {
		URL website = new URL(BASE_URL);
		ReadableByteChannel rbc = Channels.newChannel(website.openStream());
		FileOutputStream fos = new FileOutputStream("classes.jar");
		fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);

	} catch ( Exception ex) {
	ex.printStackTrace();
	}  
	 
}
0
0
0
s2smodern

W

i

l

d

F

l

y

 

c

h

e

a

t

s

h

e

e

t