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.
- Normal way to handle uploaded file via
MultipartFormDataInput
- 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?
Please comment or correct me if you have a more elegant way to get the uploaded filename.
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
byte [] bytes = IOUtils.toByteArray(inputStream);
writes the whole File to the Memory causing a OOME
how to upload multiple file using ? i am able to upload single file easily. Please help
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 🙁
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.
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
@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.
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.
its mkyong, lol
@mkyong: If i am not selecting the file to upload it says an invalid payload, how to fix this issue? Could you pls reply
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!
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.
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.
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
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.
Did you solved this problem?
Great info on this under-documented subject. Thanks a lot !!
On the getFileName function
should be like on Windows machine. I think this is also needed:
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.
Thanks
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.
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
OK got it, just drop it into a tomcat/webapp dir.
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
Hi,
Did you solved this problem? i got the same with you. so sad.
Hi,
Did you solve this problem? I am so sad, too.
get filename
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
For testing purposes I started using soapUI 4.5.1
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.
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!
see this – https://mkyong.com/webservices/jax-rs/restful-java-client-with-resteasy-client-framework/
I tried with resteasy client framework, however I got Multytype non supported error.
Here my cliente interface
and my “Form”
Could You suggest the correct way to upload a file with such client ?