Main Tutorials

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 Author

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

Comments

Subscribe
Notify of
32 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Marco
10 years ago

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

Stefan Höltker
3 years ago

byte [] bytes = IOUtils.toByteArray(inputStream);
writes the whole File to the Memory causing a OOME

aditya
5 years ago

how to upload multiple file using ? i am able to upload single file easily. Please help

Oren Hoffman
6 years ago

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 🙁

Sanjeeva Reddy
4 years ago

Hi, Mkyong, how to consume both pdf and json data ? I am calling the rest api’s through service and appending the data using the FormData in JS.

Siva
6 years ago

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

Seyed Ali Roshan
7 years ago

@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
7 years ago

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
7 years ago
Reply to  ronak

its mkyong, lol

Ragala Purushotham
7 years ago

@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
9 years ago

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
9 years ago

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.

Simon Lieschke
10 years ago

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.

Muthu
10 years ago

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
11 years ago

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
7 years ago
Reply to  satya

Did you solved this problem?

praveen
11 years ago

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

Ender Akay
11 years ago

On the getFileName function

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

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

finalFileName.replaceAll("\"", "");
edward
11 years ago

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
12 years ago

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
12 years ago

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
12 years ago
Reply to  barney

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

muhammed
12 years ago

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
11 years ago
Reply to  muhammed

Hi,

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

Dawoon Yi
10 years ago
Reply to  ken hunter

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

zhaixuepan
12 years ago

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();
            }
Diego
12 years ago

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
11 years ago
Reply to  Diego

For testing purposes I started using soapUI 4.5.1

Diego
12 years ago
Reply to  mkyong

I have this working ok, and i can test it using a simple html form but i can’t make it work with resteasy client framework
I sent a mail a week ago to the resteasy’s list but not answer
http://sourceforge.net/mailarchive/forum.php?thread_name=CAHr_oMsZkhCyo%3DWP3UP7T3sFdsO-oHORcrMrxL2xQ5yw7zbxxg%40mail.gmail.com&forum_name=resteasy-users

Can you post the client part using the resteasy client framework (not with html form)?

Thanks!

Tullio Bettinazzi
11 years ago
Reply to  mkyong

I tried with resteasy client framework, however I got Multytype non supported error.
Here my cliente interface

	@POST
	@Path("/archiviaFile")
	@Produces(MediaType.MULTIPART_FORM_DATA)
	public @MultipartForm FileUploadForm fileUpload();  

and my “Form”

public class FileUploadForm {

	private byte[] fileContent;
	@FormParam("fileName")
	@PartType(MediaType.TEXT_PLAIN)
	private String fileName;
	
	public byte[] getFileContent() {
		return fileContent;
	}

	public String getFileName() {
		return fileName;
	}


	@FormParam("uploadedFile")
	@PartType(MediaType.APPLICATION_OCTET_STREAM)
	public void setFileContent(byte[] xpFileContent) {
		fileContent = xpFileContent;
	}
	
	public void setFileName(String xpFileName) {
		fileName = xpFileName;
	}

Could You suggest the correct way to upload a file with such client ?