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
Tags :

About the Author

mkyong
Founder of Mkyong.com and HostingCompass.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

  • Pingback: water ionizer()

  • Pingback: water ionizers()

  • Pingback: streaming movies()

  • Pingback: streaming movies()

  • Pingback: free movie downloads()

  • Pingback: Blue Coaster33()

  • Pingback: JAX-RS TUTORIALS | BUYWORKSELL()

  • 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

    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.

  • praveen

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

  • Ender Akay

    On the getFileName function

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

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

    finalFileName.replaceAll(&quot;\&quot;&quot;, &quot;&quot;);
  • Pingback: JAX-RS Tutorial()

  • 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 = &quot;d:\\&quot;;

    Thanks

  • 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(&quot;securityToken&quot;)	
    	public String getFileName() {
    		return fileName;
    	}
     
    	public void setFileName(String fileName) {
    		this.fileName = fileName;
    	}
     
    	public byte[] getData() {
    		return data;
    	}
     
    	@FormParam(&quot;uploadFile&quot;)
    	@PartType(&quot;application/octet-stream&quot;)
    	public void setData(byte[] data) {
    		this.data = data;
    	}
    Select a file : &lt;input type=&quot;file&quot; name=&quot;uploadFile&quot; size=&quot;50&quot; onchange=&quot;javascript: getFilename(this.value);&quot; /&gt;
     
     
    	Security token: &lt;input type=&quot;text&quot; name=&quot;securityToken&quot; size=&quot;50&quot; /&gt;&lt;br&gt;
    	&lt;input type=&quot;submit&quot; value=&quot;Upload File&quot; /&gt;
  • 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

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

  • 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

    • http://codeforfood.net ken hunter

      Hi,

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

      • Dawoon Yi

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

  • 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();
                }
  • Pingback: File upload example in Jersey()

  • 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

    • http://www.mkyong.com mkyong

      To test it, just use a simple html form in step 2. Of course you can test it with resteasy client or other http library like Apache httpclient.

      • Diego

        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!

        • http://www.mkyong.com mkyong
          • Tullio Bettinazzi

            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 ?

    • Olimpiu POP

      For testing purposes I started using soapUI 4.5.1