Jersey (JAX-RS) supports multiple files upload. Dynamic number of files can also be uploaded.
In this tutorial we will solve following problems:
- Upload more than one files.
- Upload dynamic numbers of files. Support to upload multiple files selected using input type file with multiple files selection enabled. E.g.
<input type="file" multiple />
.
Download the source code or git clone it. Please read Jersey + Spring Boot getting started guide to run this application. This is a part of Jersey (JAX-RS) Restful Web Services Development Guides series.
1. HTML form for multiple files upload
File: /src/main/resources/static/files-upload.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Upload Files Test 2</title> </head> <body> <h2>Upload files</h2> <form action="/upload/files" enctype="multipart/form-data" method="post"> <label>Select multiple files</label><input type= "file" name="files" multiple /> <br/><br/> <label>Select File</label><input type= "file" name="file2" /> <br/><br/> <label>Tags</label> <input name="tags" maxlength="10"/> <br/><br/> <input type="submit" title="Save"/> </form> </body> </html>
This form has two file inputs. one support multiple file selections. And another single file choice.
2.1 Multiple files upload resource method – using @FormDataParam
File: /src/main/java/in/geekmj/resource/FileUploadResource.java
package in.geekmj.resource; import java.io.IOException; import java.io.InputStream; import java.nio.file.FileSystems; import java.nio.file.Files; import java.util.List; import javax.ws.rs.Consumes; import javax.ws.rs.DefaultValue; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.glassfish.jersey.media.multipart.BodyPartEntity; import org.glassfish.jersey.media.multipart.FormDataBodyPart; import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataMultiPart; import org.glassfish.jersey.media.multipart.FormDataParam; import org.springframework.stereotype.Component; /** * * @author geekmj Single File and Multiple Files upload example */ @Path("/upload") @Component public class FileUploadResource { @Path("/files") @POST @Consumes(MediaType.MULTIPART_FORM_DATA) public Response uploadFiles2(@DefaultValue("") @FormDataParam("tags") String tags, @FormDataParam("files") List<FormDataBodyPart> bodyParts, @FormDataParam("files") FormDataContentDisposition fileDispositions, @FormDataParam("file2") InputStream file2, @FormDataParam("file2") FormDataContentDisposition fileDisposition2) { StringBuffer fileDetails = new StringBuffer(""); /* Save multiple files */ for (int i = 0; i < bodyParts.size(); i++) { /* * Casting FormDataBodyPart to BodyPartEntity, which can give us * InputStream for uploaded file */ BodyPartEntity bodyPartEntity = (BodyPartEntity) bodyParts.get(i).getEntity(); String fileName = bodyParts.get(i).getContentDisposition().getFileName(); saveFile(bodyPartEntity.getInputStream(), fileName); fileDetails.append(" File saved at /Volumes/Drive2/temp/file/" + fileName); } /* Save File 2 */ String file2Name = fileDisposition2.getFileName(); saveFile(file2, file2Name); fileDetails.append(" File saved at /Volumes/Drive2/temp/file/" + file2Name); fileDetails.append(" Tag Details : " + tags); System.out.println(fileDetails); return Response.ok(fileDetails.toString()).build(); } private void saveFile(InputStream file, String name) { try { /* Change directory path */ java.nio.file.Path path = FileSystems.getDefault().getPath("/Volumes/Drive2/temp/file/" + name); /* Save InputStream as file */ Files.copy(file, path); } catch (IOException ie) { ie.printStackTrace(); } } }
Multiple files is handled using List<FormDataBodyPart>
. Similarly we have List<FormDataContentDisposition>
.
FormDataBodyPart.getEntity()
return Object. This Object is of type BodyPartEntity. BodyPartEntity.getInputStream()
method return InputStream
.
FormDataContentDisposition
can also get from FormDataBodyPart.getContentDisposition();
2.2 Multiple files upload resource method – using FormDataMultiPart
FormDataMultiPart injected automatically as Resource method parameter. Method must have @Consume(“multipart/form-data”) annotation.
FormDataMultiPart provide access to all FormDataBodyPart objects. We may can use it in place of @FormDataParam.
File: /src/main/java/in/geekmj/resource/FileUploadResource.java
package in.geekmj.resource;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.glassfish.jersey.media.multipart.BodyPartEntity;
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.springframework.stereotype.Component;
/**
*
* @author geekmj Single File and Multiple Files upload example
*/
@Path("/upload")
@Component
public class FileUploadResource {
@Path("/files2")
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFiles(final FormDataMultiPart multiPart) {
List<FormDataBodyPart> bodyParts = multiPart.getFields("files");
StringBuffer fileDetails = new StringBuffer("");
/* Save multiple files */
for (int i = 0; i < bodyParts.size(); i++) {
BodyPartEntity bodyPartEntity = (BodyPartEntity) bodyParts.get(i).getEntity();
String fileName = bodyParts.get(i).getContentDisposition().getFileName();
saveFile(bodyPartEntity.getInputStream(), fileName);
fileDetails.append(" File saved at /Volumes/Drive2/temp/file/" + fileName);
}
/* Save File 2 */
BodyPartEntity bodyPartEntity = [1]BodyPartEntity) multiPart.getField("file2").getEntity(;
String file2Name = multiPart.getField("file2").getFormDataContentDisposition().getFileName();
saveFile(bodyPartEntity.getInputStream(), file2Name);
fileDetails.append(" File saved at /Volumes/Drive2/temp/file/" + file2Name);
fileDetails.append(" Tag Details : " + multiPart.getField("tags").getValue());
System.out.println(fileDetails);
return Response.ok(fileDetails.toString()).build();
}
private void saveFile(InputStream file, String name) {
try {
/* Change directory path */
java.nio.file.Path path = FileSystems.getDefault().getPath("/Volumes/Drive2/temp/file/" + name);
/* Save InputStream as file */
Files.copy(file, path);
} catch (IOException ie) {
ie.printStackTrace();
}
}
}
3. Test multiple files upload
Go to https://localhost:8080/files-upload.html.

Change form action to /upload/files2 in /src/main/resources/static/files-upload.html to test multiple files uploading using approach 2.2.
References
- Official Jersey Documentation
- W3C multipartform/form-data documentation
- Jersey multipartform support extension maven repository
- InputStream
![]() | ![]() |
References
1. | ↑ | BodyPartEntity) multiPart.getField("file2").getEntity( |
Thanks man. This worked for me
Thanks for reading John 🙂
Thanks man. This worked for me but have a problem with charset!
When I execute the upload the file gets a strange name.
Could you help me ?
Thanks
Thanks @geekmj. I tried working the same requirement but unfortunately I’m getting one wired exception like, [ERROR ] No message body reader has been found for class org.glassfish.jersey.media.multipart.FormDataBodyPart, ContentType: multipart/form-data;boundary=————————–332263186541188574485383.
Could guess what could went wrong for the same approach as you posted the above code with websphere server?
It’s very difficult to tell why it’s behaving like it. Can you try the same code in Tomcat?