How any times do developers need an endpoint to handle file uploads? For example the user needs to upload a CSV file to make a batch insert or update.
Searching in places like StackOverflow, it is common to find that there is no stantard way to handle file uploads with JAX-RS and that implementations like Jersey or Apache CXF have some extensions to do it. That makes a project to have a dependency on an specific framework beyond the standard JavaEE/ JakartaEE / MicroProfile API’s.
A solution to this problem is to create a servlet to handle the file upload, however doing so has some disadvantages. For example developers can not use automatically interceptors or filters for JAX-RS services or make use of some MicroProfile functionalities like OpenAPI to document the API automatically.
JAX-RS internally works with a servlet that is configured automatically where developers can use that servlet to handle the file uploads in a JAX-RS way.
To do so, developers need to configure the servlet to support Multipart as a valid Content-Type in their Webservices:
That Application might look like:
package com.example;
import javax.enterprise.context.ApplicationScoped;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
@ApplicationScoped
@ApplicationPath("/api")
public class MicroProfileApplication extends Application {
}
Lets add the webapp/WEB-INF/web.xml file with this content:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<servlet>
<servlet-name>com.example.MicroProfileApplication</servlet-name>
<multipart-config>
<max-file-size>35000000</max-file-size> <!--in bytes-->
<max-request-size>218018841</max-request-size> <!--in bytes-->
<file-size-threshold>0</file-size-threshold> <!--in bytes-->
</multipart-config>
</servlet>
<servlet-mapping>
<servlet-name>com.example.MicroProfileApplication</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
</web-app>
Once the project is configured, developers can start writing Webservices like:
@POST
@Path("/upload")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public String uploadTest(@Context HttpServletRequest request){
try{
Part file = request.getPart("file"); //file is the name of the parameter on the request.
InputStream fileContent = file.getInputStream();
//do something with the file.
return "Ok";
}
catch (IOException | ServletException ex){
//Do some exception management
return "error";
}
}
For example you can read the contents of a text file like this:
@POST
@Path("/upload")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public String uploadTest(@Context HttpServletRequest request){
try{
Part file = request.getPart("file"); //file is the name of the parameter on the request.
InputStream fileContent = file.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(fileContent, StandardCharsets.UTF_8.name()));
StringBuilder value = new StringBuilder();
char[] buffer = new char[1024];
for (int length; (length = reader.read(buffer)) > 0; )
{
value.append(buffer, 0, length);
}
return value.toString();
}
catch (IOException | ServletException ex){
//Do some exception management
return "error";
}
}
Now, developers can consume our Webservice in this way: Or from any client using the Content-Type: multipart/form-data