File upload example in RESTEasy

Not many complete file upload example in JAX-RS, especially RESTEasy. Here, we show you two complete RESTEasy examples to handle file upload from HTML form.

  1. Normal way to handle uploaded file via MultipartFormDataInput
  2. Map uploaded file to a POJO class via @MultipartForm

1. RESTEasy Multipart Dependency

In RESTEasy, you need “resteasy-multipart-provider.jar” to handle multipart file upload.

File : pom.xml


	<dependency>
		<groupId>org.jboss.resteasy</groupId>
		<artifactId>resteasy-jaxrs</artifactId>
		<version>2.2.1.GA</version>
	</dependency>

	<dependency>
		<groupId>org.jboss.resteasy</groupId>
		<artifactId>resteasy-multipart-provider</artifactId>
		<version>2.2.0.GA</version>
	</dependency>

	<!-- optional, good for handle I/O task -->
	<dependency>
		<groupId>commons-io</groupId>
		<artifactId>commons-io</artifactId>
		<version>2.0.1</version>
	</dependency>

2. File Upload HTML Form

Simple HTML form to upload file.


<html>
<body>
	<h1>JAX-RS Upload Form</h1>

	<form action="rest/file/upload" method="post" enctype="multipart/form-data">
		
	   <p>
		Select a file : <input type="file" name="uploadedFile" size="50" />
	   </p>

	   <input type="submit" value="Upload It" />
	</form>

</body>
</html>

3.1 MultipartFormDataInput example

First example, the uploaded file will map to “MultipartFormDataInput” automatically.


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.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import org.apache.commons.io.IOUtils;
import org.jboss.resteasy.plugins.providers.multipart.InputPart;
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;

@Path("/file")
public class UploadFileService {

	private final String UPLOADED_FILE_PATH = "d:\\";
	
	@POST
	@Path("/upload")
	@Consumes("multipart/form-data")
	public Response uploadFile(MultipartFormDataInput input) {

		String fileName = "";
		
		Map<String, List<InputPart>> uploadForm = input.getFormDataMap();
		List<InputPart> inputParts = uploadForm.get("uploadedFile");

		for (InputPart inputPart : inputParts) {

		 try {

			MultivaluedMap<String, String> header = inputPart.getHeaders();
			fileName = getFileName(header);

			//convert the uploaded file to inputstream
			InputStream inputStream = inputPart.getBody(InputStream.class,null);

			byte [] bytes = IOUtils.toByteArray(inputStream);
				
			//constructs upload file path
			fileName = UPLOADED_FILE_PATH + fileName;
				
			writeFile(bytes,fileName);
				
			System.out.println("Done");

		  } catch (IOException e) {
			e.printStackTrace();
		  }

		}

		return Response.status(200)
		    .entity("uploadFile is called, Uploaded file name : " + fileName).build();

	}

	/**
	 * header sample
	 * {
	 * 	Content-Type=[image/png], 
	 * 	Content-Disposition=[form-data; name="file"; filename="filename.extension"]
	 * }
	 **/
	//get uploaded filename, is there a easy way in RESTEasy?
	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";
	}

	//save to somewhere
	private void writeFile(byte[] content, String filename) throws IOException {

		File file = new File(filename);

		if (!file.exists()) {
			file.createNewFile();
		}

		FileOutputStream fop = new FileOutputStream(file);

		fop.write(content);
		fop.flush();
		fop.close();

	}
}

In this example, if you select a file “c:\\abc.png” from your local C drive, click on the submit button, then it will uploaded to “d:\\abc.png“.

3.2 MultipartForm example

This example will map the uploaded file to a POJO class, you dun need to handle the inputPart like 3.1 example.

POJO file, map uploaded file to this class.


import javax.ws.rs.FormParam;
import org.jboss.resteasy.annotations.providers.multipart.PartType;

public class FileUploadForm {

	public FileUploadForm() {
	}
	
	private byte[] data;

	public byte[] getData() {
		return data;
	}

	@FormParam("uploadedFile")
	@PartType("application/octet-stream")
	public void setData(byte[] data) {
		this.data = data;
	}
	
}

Handle the uploaded file.


import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import org.jboss.resteasy.annotations.providers.multipart.MultipartForm;

@Path("/file")
public class UploadFileService {

	@POST
	@Path("/upload")
	@Consumes("multipart/form-data")
	public Response uploadFile(@MultipartForm FileUploadForm form) {

		String fileName = "d:\\anything";
		
		try {
			writeFile(form.getData(), fileName);
		} catch (IOException e) {
			
			e.printStackTrace();
		}

		System.out.println("Done");

		return Response.status(200)
		    .entity("uploadFile is called, Uploaded file name : " + fileName).build();

	}

	// save to somewhere
	private void writeFile(byte[] content, String filename) throws IOException {

		File file = new File(filename);

		if (!file.exists()) {
			file.createNewFile();
		}

		FileOutputStream fop = new FileOutputStream(file);

		fop.write(content);
		fop.flush();
		fop.close();

	}
}

The problem is, you can’t get the uploaded filename! To fix it, you can put a textbox in HTML form, so that user is able to key in the uploaded filename, and map it to “FileUploadForm” via @FormParam("filename").

Conclusion

Overall, RESTEasy is able to handle multipart well, but it’s rather hard to get the uploaded file header information, like filename. Or, may be i do not know how to use the RESTEasy API?

Note
Please comment or correct me if you have a more elegant way to get the uploaded filename.

References

  1. How do I do a multipart/form file upload with jax-rs?
  2. Resteasy multipart/data-form file upload on GAE

About the Author

author image
mkyong
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter, or befriend him on Facebook or Google Plus. If you like my tutorials, consider make a donation to these charities.

Comments

Leave a Reply

avatar
newest oldest most voted
Siva
Guest
Siva

I would like to override the tmp location. During upload, the file is creating on /tmp (Example: m4j1405606050480316167.tmp). I would like to create these dummy files during upload into my customize directory.

I tried to introduce web.xml like this for overwrite location.

UploadApplication

/var/tmp

UploadApplication
/rest/*

But, it is not working.

FYI: i am using
org.jboss.resteasy
resteasy-multipart-provider
2.3.6.Final

Oren Hoffman
Guest
Oren Hoffman

thank you for this example, im facing an issue of class pathes, when im trying to coppy it to anywhere in the pc its all perfecr BUT when im trying to coppy it to the project class path im getting the “The system cannot find the path specified” no metter what class path im passing, im running it on wildfly10.0 , im tyring to upload an image file to webContent/image , but eventually what happend is that hes creating 2 foldars in the bin directory in the wildfly

Please help man :(

Seyed Ali Roshan
Guest
Seyed Ali Roshan

@mkyong
hello,
I load exactly a copy of your codes, but I received error 500.
the error is:
“HTTP Status 500 – java.lang.RuntimeException: Could find no Content-Disposition header within part”
I even set Content-Disposition in below forms:
Content-Disposition:form-data;name=”exampleName”;filename=”MyFile(exampleFile).extension”
for example for image file
Content-Disposition:form-data;name=”exampleName”;filename=”background.png”

Content-Disposition:attachment;
and some other ways but got same error 500 for all of them.

I used both ways that you put on this post and got error 500 from both of them.
what’s the problem, please guide me.
by the way, thanks for your perfect site.

ronak
Guest
ronak

Hi mykong,
I will be great if you can specify how to create file upload operation using Java instead of HTML form opeartion. like using MultipartEntity etc.

Phada
Guest
Phada

its mkyong, lol

Ragala Purushotham
Guest
Ragala Purushotham

@mkyong: If i am not selecting the file to upload it says an invalid payload, how to fix this issue? Could you pls reply

DS
Guest
DS

Good article! What would be the best way to validate the uploaded files? We have a scenario where we need to check that the file is an image (we don’t know what all extensions are valid, so we can’t check just that). Thank you!

Aye Min Oo
Guest
Aye Min Oo

When I uploaded English file name, it is ok. But when I uploaded unicode file name, this unicode name become unreadable like ?????????.jpg . How can I do to get the same unicode name on server side. Thank you, MKyoung.

Marco
Guest
Marco

not working getting following exception Could find no Content-Disposition header within part

POST /SimpleRestWebservice/rest/search/create HTTP/1.1
Host: localhost:8080
Content-Type: multipart/form-data; boundary=E19zNvXGzXaLvS5C
Cache-Control: no-cache
Connection: keep-alive
Cache-Control: no-cache

—-WebKitFormBoundaryE19zNvXGzXaLvS5C
Content-Disposition: form-data; name=”file”; filename=”test.doc”
Content-Type: application/msword

—-WebKitFormBoundaryE19zNvXGzXaLvS5C

dont know why whats wrong

Simon Lieschke
Guest
Simon Lieschke

It’s not a good idea to use untrusted information from the client to work out the path to save the file on the file system. This could easily be exploited to attack the system. See https://www.owasp.org/index.php/Unrestricted_File_Upload for more details about why this is extremely bad practise.

It would be great if you could update your example as many people won’t read down to the comments.

trackback
JAX-RS TUTORIALS | BUYWORKSELL

[…] File upload example in RESTEasy Two ways to handle file upload in RESTEasy. […]

Muthu
Guest
Muthu

hey,
what is the jar name or where to download, i couldn’t find the jar for
org.jboss.resteasy.annotations.providers.multipart.PartType
and
com.sun.jersey.core.header.FormDataContentDisposition

satya
Guest
satya

After submitting it

http://localhost:8080/RESTfulExample/UploadForm.html

I am getting following error

HTTP ERROR 404

Problem accessing /RESTfulExample/rest/file/upload. Reason:

Could not find resource for relative : /file/upload of full path: http://localhost:8080/RESTfulExample/rest/file/upload

Please provide solution.

abdelaziz chibi
Guest
abdelaziz chibi

Did you solved this problem?

praveen
Guest
praveen

Great info on this under-documented subject. Thanks a lot !!

Ender Akay
Guest
Ender Akay

On the getFileName function

String finalFileName = name[1].trim().replaceAll("\\\\", ""); 

should be like on Windows machine. I think this is also needed:

finalFileName.replaceAll("\"", "");
trackback
JAX-RS Tutorial

[…] File upload example in RESTEasy Two ways to handle file upload in RESTEasy. […]

edward
Guest
edward

Everything works fine, but how do I do to get a relative path to my project so the file gets uploaded into c:\\users\\documents\\netbeans\\myproject\\src\\folderToUpload.

Actually you are storing the file in a manually writen location, I want to generate this location because when I upload the file to the server (linux) it has to work fine in the server too.

private final String UPLOADED_FILE_PATH = "d:\\"; 

Thanks

noman ali
Guest
noman ali

Hi,
Nice article but i m facing a problem, as you mentioned create a textbox in html form and get it via @FormParam but unfortunately i m unable to get it.

private byte[] data;
	private String fileName;
	
	@FormParam("securityToken")	
	public String getFileName() {
		return fileName;
	}
	
	public void setFileName(String fileName) {
		this.fileName = fileName;
	}

	public byte[] getData() {
		return data;
	}
 
	@FormParam("uploadFile")
	@PartType("application/octet-stream")
	public void setData(byte[] data) {
		this.data = data;
	}
Select a file : <input type="file" name="uploadFile" size="50" onchange="javascript: getFilename(this.value);" />


	Security token: <input type="text" name="securityToken" size="50" /><br>
	<input type="submit" value="Upload File" />
barney
Guest
barney

Hi Mkyong,

How do you run this project? I downloaded your zip file and unzipped it, but noticed you’re not using jetty. Thanks, great site.

Barney

barney
Guest
barney

OK got it, just drop it into a tomcat/webapp dir.

muhammed
Guest
muhammed

hi i use it but when i post from html
it gives me The request sent by the client was syntactically incorrect (java.lang.RuntimeException: Could find no Content-Disposition header within part).
error please help

ken hunter
Guest
ken hunter

Hi,

Did you solved this problem? i got the same with you. so sad.

Dawoon Yi
Guest
Dawoon Yi

Hi,
Did you solve this problem? I am so sad, too.

zhaixuepan
Guest
zhaixuepan
get filename MultivaluedMap heades = part.getHeaders(); String CDHeader = heades.getFirst("Content-Disposition"); String fileName =""; Pattern p = Pattern.compile("filename=\".*\""); Matcher m = p.matcher(CDHeader); if (m.find()){ fileName = m.group(); }
trackback
File upload example in Jersey

[…] Download it – JAX-RS-FileUpload-Jersey-Example.zip (6 KB)ReferencesJersey Official WebsiteFile Upload example in RESTEasy […]

Diego
Guest
Diego

Hi mkyong, how did you test this? And how could you do that using resteasy-client part?

Thanks for this articule, it was very helpfull

Diego

Olimpiu POP
Guest
Olimpiu POP

For testing purposes I started using soapUI 4.5.1