Configuring a resource to receive multipart/form-data parts from an HTML form submission in JAX-RS 2.0

HTML forms that transmit file data must be configured with the POST method and the "multipart/form-data" action. The resource method executing in IBM's implementation of the Java™ API for RESTful Web Services (JAX-RS) specification can receive this data in one of the two ways.

About this task

Open LibertyThe most recent documentation for multipart/form-data parts in JAX-RS 2.0 and later is available on the Open Liberty website.

In Jakarta Restful Web Services 3.0 and earlier, support for sending and receiving multipart/form-data parts was provided by the Liberty-specific IAttachment and IMultipartBodyAPIs, which are deprecated in version 3.1, which is included in Liberty 23.0.0.3. In this version and later, this support is provided by the EntityPart API that is defined in the RESTful Web Services specification. For more information, see section 3.5.2 of the Jakarta Restful Web Services specification.

and

This task provides instructions for configuring a JAX-RS method to use and produce multipart/form-data. The following example illustrates an HTML form:
<form action="http://www.example.com/" method="POST" enctype="multipart/form-data">
    <input type="text" name="fileid" />
    <br />
    <input type="text" name="description" />
    <br />
    <input type="file" name="thefile" />
    <br />
    <input type="submit" name="submit" value="submit"/>
</form>
You can implement your JAX-RS resource method to receive the data in parts, so you can process these parts yourself, if needed.

Procedure

Create a resource method.
You must declare one of the following resource methods to receive and echo multipart/form-data content from an HTTP POST:

@POST
@Consumes("multipart/form-data")
@Produces("multipart/form-data")

public Response postFormData(IMultipartBody multipartBody) {
    List <IAttachment> attachments = multipartBody.getAllAttachments();
    String formElementValue = null; 
    InputStream stream = null;
    for (Iterator<IAttachment> it = attachments.iterator(); it.hasNext();) {
         IAttachment attachment = it.next();
         if (attachment == null) {
             continue;
         }
         DataHandler dataHandler = attachment.getDataHandler();
         stream = dataHandler.getInputStream();
         MultivaluedMap<String, String> map = attachment.getHeaders();
         String fileName = null;
         String formElementName = null;
         String[] contentDisposition = map.getFirst("Content-Disposition").split(";");
         for (String tempName : contentDisposition) {
              String[] names = tempName.split("=");
              formElementName = names[1].trim().replaceAll("\"", "");
              if ((tempName.trim().startsWith("filename"))) {
                   fileName = formElementName;
              }
         }
         if (fileName == null) {
             StringBuffer sb = new StringBuffer();
             BufferedReader br = new BufferedReader(new InputStreamReader(stream));
             String line = null;
             try {
                 while ((line = br.readLine()) != null) {
                    sb.append(line);
                 }
             } catch (IOException e) {
                 e.printStackTrace();
             } finally {
                 if (br != null) {
                     try {
                          br.close();
                     } catch (IOException e) {
                         e.printStackTrace();
                     }
                 }
             }
             formElementValue = sb.toString();
             System.out.println(formElementName + ":" + formElementValue);
         } else {
             //handle the file as you want
             File tempFile = new File(fileName);
             ...
         }
    }
    if (stream != null) {
        stream.close();
    }
    return Response.ok("test").build();
}
Or

@POST
@Consumes("multipart/form-data")
@Produces("multipart/form-data")

public Response postFormData(IMultipartBody multipartBody) {
    List <IAttachment> attachments = multipartBody.getAllAttachments();
    String formElementValue = null; 
    InputStream stream = null;
    for (Iterator<IAttachment> it = attachments.iterator(); it.hasNext();) {
         IAttachment attachment = it.next();
         if (attachment == null) {
             continue;
         }
         DataHandler dataHandler = attachment.getDataHandler();
         stream = dataHandler.getInputStream();
         MultivaluedMap<String, String> map = attachment.getHeaders();
         String fileName = null;
         String formElementName = null;
         String[] contentDisposition = map.getFirst("Content-Disposition").split(";");
         for (String tempName : contentDisposition) {
             String[] names = tempName.split("=");
             formElementName = names[1].trim().replaceAll("\"", "");
             if ((tempName.trim().startsWith("filename"))) {
                 fileName = formElementName;
             }
         }
         if (fileName == null) {
             StringBuffer sb = new StringBuffer();
             BufferedReader br = new BufferedReader(new InputStreamReader(stream));
             String line = null;
             try {
                 while ((line = br.readLine()) != null) {
                     sb.append(line);
                 }
             } catch (IOException e) {
                 e.printStackTrace();
             } finally {
                 if (br != null) {
                     try {
                         br.close();
                     } catch (IOException e) {
                         e.printStackTrace();
                     }
                 }
             }
             formElementValue = sb.toString();
             System.out.println(formElementName + ":" + formElementValue);
         } else {
             //handle the file as you want
             File tempFile = new File(fileName);
             ...
         }
    }
    if (stream != null) {
        stream.close();
    }
    return Response.ok("test").build();
}
The originator of the form POST submission can generate a Content-Transfer-Encoding header for one or more parts of the multipart message. The IBM JAX-RS implementation attempts to auto-decode the payload of the part according to this header when the header is of base64 or quoted-printable encoding type.

Results

Your resource method will receive and echo data from an HTTP POST with multipart/form-data Content-Type. IBM's JAX-RS implementation will split and auto-decode the parts for you, allowing the application code in the resource method to process the form data.