Java File Upload REST service

In this tutorial I will explain how to build Java REST web-service to upload files from any client over HTTP.

Uploading files to web-apps is a common task nowadays. A lot of services support uploading pictures or documents on their sites. With Java web services this is easy accomplished. What we need aside form the java web container (provided by your application server like Tomcat, GlassFish or JBoss) is the jersey framework to make it run. First I will show you how to implement the web-service and than give you two examples of clients to use the service.

Java file upload form

Java file upload form

Building the File Upload REST Service

The file is pushed over HTTP POST with encoding type “multipart/form-data” from the client to our web-service. This way you can add multiple parameters to the POST request in addition to the file. Lets start with the requirements. You will need an web/application server like Tomcat, GlassFish or JBoss to deploy the service. In addition we will use jersey framework to build our service endpoint. Please note, GlassFish 4.x version requires jersey version 2 libraries, so if you are using GlassFish 4 use jersey 2.x dependencies in your POM file instead.

For quick reference you can find the entire project in our GitHub repository under https://github.com/JavaTutorialNetwork/Tutorials/tree/master/FileUploaderRESTService

I will post the entire POM file here, but what you need to take into account are the jersey dependencies

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  3. <modelVersion>4.0.0</modelVersion>
  4. <groupId>net.javatutorial.tutorials</groupId>
  5. <artifactId>FileUploaderRESTService</artifactId>
  6. <version>1</version>
  7. <packaging>war</packaging>
  8. <name>File Uploader Rest Service</name>
  9. <url>https://javatutorial.net</url>
  10. <properties>
  11. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  12. </properties>
  13. <dependencies>
  14. <dependency>
  15. <groupId>com.sun.jersey</groupId>
  16. <artifactId>jersey-server</artifactId>
  17. <version>1.8</version>
  18. </dependency>
  19. <dependency>
  20. <groupId>com.sun.jersey</groupId>
  21. <artifactId>jersey-servlet</artifactId>
  22. <version>1.17.1</version>
  23. </dependency>
  24. <dependency>
  25. <groupId>com.sun.jersey</groupId>
  26. <artifactId>jersey-json</artifactId>
  27. <version>1.8</version>
  28. </dependency>
  29. <dependency>
  30. <groupId>com.sun.jersey.contribs</groupId>
  31. <artifactId>jersey-multipart</artifactId>
  32. <version>1.8</version>
  33. </dependency>
  34. </dependencies>
  35. <build>
  36. <plugins>
  37. <plugin>
  38. <groupId>org.apache.maven.plugins</groupId>
  39. <artifactId>maven-compiler-plugin</artifactId>
  40. <version>3.1</version>
  41. <inherited>true</inherited>
  42. <configuration>
  43. <source>1.7</source>
  44. <target>1.7</target>
  45. </configuration>
  46. </plugin>
  47. <plugin>
  48. <artifactId>maven-war-plugin</artifactId>
  49. <version>2.3</version>
  50. <configuration>
  51. <webXml>src/main/webapp/WEB-INF/web.xml</webXml>
  52. <webResources>
  53. <resource>
  54. <!-- this is relative to the pom.xml directory -->
  55. <directory>${project.basedir}/src/main/resources
  56. </directory>
  57. </resource>
  58. </webResources>
  59. </configuration>
  60. </plugin>
  61. </plugins>
  62. </build>
  63. </project>
<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>net.javatutorial.tutorials</groupId>
	<artifactId>FileUploaderRESTService</artifactId>
	<version>1</version>
	<packaging>war</packaging>

	<name>File Uploader Rest Service</name>
	<url>https://javatutorial.net</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>com.sun.jersey</groupId>
			<artifactId>jersey-server</artifactId>
			<version>1.8</version>
		</dependency>
		<dependency>
			<groupId>com.sun.jersey</groupId>
			<artifactId>jersey-servlet</artifactId>
			<version>1.17.1</version>
		</dependency>
		<dependency>
			<groupId>com.sun.jersey</groupId>
			<artifactId>jersey-json</artifactId>
			<version>1.8</version>
		</dependency>
		<dependency>
			<groupId>com.sun.jersey.contribs</groupId>
			<artifactId>jersey-multipart</artifactId>
			<version>1.8</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<inherited>true</inherited>
				<configuration>
					<source>1.7</source>
					<target>1.7</target>
				</configuration>
			</plugin>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>2.3</version>
				<configuration>
					<webXml>src/main/webapp/WEB-INF/web.xml</webXml>
					<webResources>
						<resource>
							<!-- this is relative to the pom.xml directory -->
							<directory>${project.basedir}/src/main/resources
							</directory>
						</resource>
					</webResources>
				</configuration>
			</plugin>
		</plugins>
	</build>

</project>

Having all necessary libraries now, lets go ahead and implement the REST service. There are several places in the code below I want to point your attention to. First note the usage of @Consumes(MediaType.MULTIPART_FORM_DATA) as requested encoding type. Second you may want to add additional parameters to the method if you like. For example you may want to pass some description or another text data with your upload. Finally Java will throw an Exception if you try to upload a file into a directory which not exists.  To avoid this issue I created the method createFolderIfNotExists(String dirName).

  1. package net.javatutorial.tutorials.services;
  2. import java.io.File;
  3. import java.io.FileOutputStream;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. import java.io.OutputStream;
  7. import javax.ws.rs.Consumes;
  8. import javax.ws.rs.POST;
  9. import javax.ws.rs.Path;
  10. import javax.ws.rs.core.Context;
  11. import javax.ws.rs.core.MediaType;
  12. import javax.ws.rs.core.Response;
  13. import javax.ws.rs.core.UriInfo;
  14. import com.sun.jersey.core.header.FormDataContentDisposition;
  15. import com.sun.jersey.multipart.FormDataParam;
  16. /**
  17. * This example shows how to build Java REST web-service to upload files
  18. * accepting POST requests with encoding type "multipart/form-data". For more
  19. * details please read the full tutorial on
  20. * https://javatutorial.net/java-file-upload-rest-service
  21. *
  22. * @author javatutorial.net
  23. */
  24. @Path("/upload")
  25. public class FileUploadService {
  26. /** The path to the folder where we want to store the uploaded files */
  27. private static final String UPLOAD_FOLDER = "c:/uploadedFiles/";
  28. public FileUploadService() {
  29. }
  30. @Context
  31. private UriInfo context;
  32. /**
  33. * Returns text response to caller containing uploaded file location
  34. *
  35. * @return error response in case of missing parameters an internal
  36. * exception or success response if file has been stored
  37. * successfully
  38. */
  39. @POST
  40. @Consumes(MediaType.MULTIPART_FORM_DATA)
  41. public Response uploadFile(
  42. @FormDataParam("file") InputStream uploadedInputStream,
  43. @FormDataParam("file") FormDataContentDisposition fileDetail) {
  44. // check if all form parameters are provided
  45. if (uploadedInputStream == null || fileDetail == null)
  46. return Response.status(400).entity("Invalid form data").build();
  47. // create our destination folder, if it not exists
  48. try {
  49. createFolderIfNotExists(UPLOAD_FOLDER);
  50. } catch (SecurityException se) {
  51. return Response.status(500)
  52. .entity("Can not create destination folder on server")
  53. .build();
  54. }
  55. String uploadedFileLocation = UPLOAD_FOLDER + fileDetail.getFileName();
  56. try {
  57. saveToFile(uploadedInputStream, uploadedFileLocation);
  58. } catch (IOException e) {
  59. return Response.status(500).entity("Can not save file").build();
  60. }
  61. return Response.status(200)
  62. .entity("File saved to " + uploadedFileLocation).build();
  63. }
  64. /**
  65. * Utility method to save InputStream data to target location/file
  66. *
  67. * @param inStream
  68. * - InputStream to be saved
  69. * @param target
  70. * - full path to destination file
  71. */
  72. private void saveToFile(InputStream inStream, String target)
  73. throws IOException {
  74. OutputStream out = null;
  75. int read = 0;
  76. byte[] bytes = new byte[1024];
  77. out = new FileOutputStream(new File(target));
  78. while ((read = inStream.read(bytes)) != -1) {
  79. out.write(bytes, 0, read);
  80. }
  81. out.flush();
  82. out.close();
  83. }
  84. /**
  85. * Creates a folder to desired location if it not already exists
  86. *
  87. * @param dirName
  88. * - full path to the folder
  89. * @throws SecurityException
  90. * - in case you don't have permission to create the folder
  91. */
  92. private void createFolderIfNotExists(String dirName)
  93. throws SecurityException {
  94. File theDir = new File(dirName);
  95. if (!theDir.exists()) {
  96. theDir.mkdir();
  97. }
  98. }
  99. }
package net.javatutorial.tutorials.services;

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.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

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

/**
 * This example shows how to build Java REST web-service to upload files
 * accepting POST requests with encoding type "multipart/form-data". For more
 * details please read the full tutorial on
 * https://javatutorial.net/java-file-upload-rest-service
 * 
 * @author javatutorial.net
 */
@Path("/upload")
public class FileUploadService {

	/** The path to the folder where we want to store the uploaded files */
	private static final String UPLOAD_FOLDER = "c:/uploadedFiles/";

	public FileUploadService() {
	}

	@Context
	private UriInfo context;

	/**
	 * Returns text response to caller containing uploaded file location
	 * 
	 * @return error response in case of missing parameters an internal
	 *         exception or success response if file has been stored
	 *         successfully
	 */
	@POST
	@Consumes(MediaType.MULTIPART_FORM_DATA)
	public Response uploadFile(
			@FormDataParam("file") InputStream uploadedInputStream,
			@FormDataParam("file") FormDataContentDisposition fileDetail) {

		// check if all form parameters are provided
		if (uploadedInputStream == null || fileDetail == null)
			return Response.status(400).entity("Invalid form data").build();

		// create our destination folder, if it not exists
		try {
			createFolderIfNotExists(UPLOAD_FOLDER);
		} catch (SecurityException se) {
			return Response.status(500)
					.entity("Can not create destination folder on server")
					.build();
		}

		String uploadedFileLocation = UPLOAD_FOLDER + fileDetail.getFileName();
		try {
			saveToFile(uploadedInputStream, uploadedFileLocation);
		} catch (IOException e) {
			return Response.status(500).entity("Can not save file").build();
		}

		return Response.status(200)
				.entity("File saved to " + uploadedFileLocation).build();
	}

	/**
	 * Utility method to save InputStream data to target location/file
	 * 
	 * @param inStream
	 *            - InputStream to be saved
	 * @param target
	 *            - full path to destination file
	 */
	private void saveToFile(InputStream inStream, String target)
			throws IOException {
		OutputStream out = null;
		int read = 0;
		byte[] bytes = new byte[1024];

		out = new FileOutputStream(new File(target));
		while ((read = inStream.read(bytes)) != -1) {
			out.write(bytes, 0, read);
		}
		out.flush();
		out.close();
	}

	/**
	 * Creates a folder to desired location if it not already exists
	 * 
	 * @param dirName
	 *            - full path to the folder
	 * @throws SecurityException
	 *             - in case you don't have permission to create the folder
	 */
	private void createFolderIfNotExists(String dirName)
			throws SecurityException {
		File theDir = new File(dirName);
		if (!theDir.exists()) {
			theDir.mkdir();
		}
	}

}

Finally we need to configure our web.xml to register our class as web-service and make it run on startup.

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
  4. xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
  5. id="WebApp_ID" version="2.5">
  6. <display-name>net.javatutorial.tutorials.services</display-name>
  7. <servlet>
  8. <servlet-name>Jersey REST Service</servlet-name>
  9. <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
  10. <init-param>
  11. <param-name>com.sun.jersey.config.property.packages</param-name>
  12. <param-value>net.javatutorial.tutorials.services</param-value>
  13. </init-param>
  14. <load-on-startup>1</load-on-startup>
  15. </servlet>
  16. <servlet-mapping>
  17. <servlet-name>Jersey REST Service</servlet-name>
  18. <url-pattern>/rest/*</url-pattern>
  19. </servlet-mapping>
  20. </web-app>
<?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>net.javatutorial.tutorials.services</display-name>
	<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>net.javatutorial.tutorials.services</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>

That’s it! Now you can build and deploy the WAR file. If you use the exact same names provided in the code above, your service URL (given you run on localhost) will be: http://localhost:8080/FileUploaderRESTService-1/rest/upload

File Upload HTML Form

You can use a very simple HTML post form as client to send files to the server.

Please note the usage of “multipart/form-data” as encoding type. You also need to add an <input> of type file with the name “file”

  1. Choose file to upload<br>
  2. <form action="http://localhost:8080/FileUploaderRESTService-1/rest/upload" method="post" enctype="multipart/form-data">
  3. <input name="file" id="filename" type="file" /><br><br>
  4. <button name="submit" type="submit">Upload</button>
  5. </form>
Choose file to upload<br>
<form action="http://localhost:8080/FileUploaderRESTService-1/rest/upload" method="post" enctype="multipart/form-data">
	<input name="file" id="filename" type="file" /><br><br>
	<button name="submit" type="submit">Upload</button>
</form>

As I already mentioned you can add additional data to your request. In this case just don’t forget to handle it in the web-service 🙂

Java File Upload Client

You can create a file upload client for you Android or stand-alone programs in java. I the example below I will use Apache http libraries, you will need this five:

  • commons-logging
  • httpclient
  • httpclient-cache
  • httpcore
  • httpmime
  1. package net.javatutorial.tutorials.clienst;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.IOException;
  5. import org.apache.http.HttpEntity;
  6. import org.apache.http.HttpResponse;
  7. import org.apache.http.client.ClientProtocolException;
  8. import org.apache.http.client.methods.HttpPost;
  9. import org.apache.http.entity.mime.MultipartEntity;
  10. import org.apache.http.entity.mime.content.InputStreamBody;
  11. import org.apache.http.impl.client.DefaultHttpClient;
  12. import org.apache.http.params.BasicHttpParams;
  13. import org.apache.http.util.EntityUtils;
  14. /**
  15. * This example shows how to upload files using POST requests
  16. * with encoding type "multipart/form-data".
  17. * For more details please read the full tutorial
  18. * on https://javatutorial.net/java-file-upload-rest-service
  19. * @author javatutorial.net
  20. */
  21. public class FileUploaderClient {
  22. public static void main(String[] args) {
  23. // the file we want to upload
  24. File inFile = new File("C:\\Users\\admin\\Desktop\\Yana-make-up.jpg");
  25. FileInputStream fis = null;
  26. try {
  27. fis = new FileInputStream(inFile);
  28. DefaultHttpClient httpclient = new DefaultHttpClient(new BasicHttpParams());
  29. // server back-end URL
  30. HttpPost httppost = new HttpPost("http://localhost:8080/FileUploaderRESTService-1/rest/upload");
  31. MultipartEntity entity = new MultipartEntity();
  32. // set the file input stream and file name as arguments
  33. entity.addPart("file", new InputStreamBody(fis, inFile.getName()));
  34. httppost.setEntity(entity);
  35. // execute the request
  36. HttpResponse response = httpclient.execute(httppost);
  37. int statusCode = response.getStatusLine().getStatusCode();
  38. HttpEntity responseEntity = response.getEntity();
  39. String responseString = EntityUtils.toString(responseEntity, "UTF-8");
  40. System.out.println("[" + statusCode + "] " + responseString);
  41. } catch (ClientProtocolException e) {
  42. System.err.println("Unable to make connection");
  43. e.printStackTrace();
  44. } catch (IOException e) {
  45. System.err.println("Unable to read file");
  46. e.printStackTrace();
  47. } finally {
  48. try {
  49. if (fis != null) fis.close();
  50. } catch (IOException e) {}
  51. }
  52. }
  53. }
package net.javatutorial.tutorials.clienst;

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

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.InputStreamBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.util.EntityUtils;

/**
 * This example shows how to upload files using POST requests 
 * with encoding type "multipart/form-data".
 * For more details please read the full tutorial
 * on https://javatutorial.net/java-file-upload-rest-service
 * @author javatutorial.net
 */
public class FileUploaderClient {
	
	public static void main(String[] args) {
		
		// the file we want to upload
		File inFile = new File("C:\\Users\\admin\\Desktop\\Yana-make-up.jpg");
		FileInputStream fis = null;
		try {
			fis = new FileInputStream(inFile);
			DefaultHttpClient httpclient = new DefaultHttpClient(new BasicHttpParams());
			
			// server back-end URL
			HttpPost httppost = new HttpPost("http://localhost:8080/FileUploaderRESTService-1/rest/upload");
			MultipartEntity entity = new MultipartEntity();

			// set the file input stream and file name as arguments
			entity.addPart("file", new InputStreamBody(fis, inFile.getName()));
			httppost.setEntity(entity);

			// execute the request
			HttpResponse response = httpclient.execute(httppost);
			
			int statusCode = response.getStatusLine().getStatusCode();
			HttpEntity responseEntity = response.getEntity();
			String responseString = EntityUtils.toString(responseEntity, "UTF-8");
			
			System.out.println("[" + statusCode + "] " + responseString);
			
		} catch (ClientProtocolException e) {
			System.err.println("Unable to make connection");
			e.printStackTrace();
		} catch (IOException e) {
			System.err.println("Unable to read file");
			e.printStackTrace();
		} finally {
			try {
				if (fis != null) fis.close();
			} catch (IOException e) {}
		}
	}
	
}

You will find the project files in our GitHub repository https://github.com/JavaTutorialNetwork/Tutorials/tree/master/FileUploaderJavaClient

Thanks for reading. As always comments are welcome 🙂