Skip to main content

Writing Attachments

It is possible to write attachments to the output stream, both on the client and server sides.

On the server side it is sufficient to update the @Produces value for a given method:

public class Resource {
   private List<Book> books; 
   @Produces("multipart/mixed;type=text/xml")
   public List<Book> getBooksAsMultipart() {
      return booksList;
   }

   @Produces("multipart/mixed;type=text/xml")
   public Book getBookAsMultipart() {
      return booksList;
   }
}

Note that a 'type' parameter of the 'multipart/mixed' media type indicates that all parts in the multiparts response should have a Content-Type header set to 'text/xml' for both getBooksAsMultipart() and getBookAsMultipart() method responses. The getBooksAsMultipart() response will have 3 parts, the first part will have its Content-ID header set to "root.message@cxf.apache.org", the next parts will have '1' and '2' ids. The getBookAsMultipart() response will have a single part only with its Content-ID header set to "root.message@cxf.apache.org".

When returning mixed multiparts containing objects of different types, you can either return a Map with the media type string value to Object pairs or MultipartBody:

public class Resource {
   private List<Book> books; 
   @Produces("multipart/mixed")
   public Map<String, Object> getBooks() {
      Map<String, Object> map = new LinkedHashMap<String, Object>();
      map.put("text/xml", new JaxbBook());
      map.put("application/json", new JSONBook());
      map.put("application/octet-stream", imageInputStream);
      return map;  
   } 

   @Produces("multipart/mixed")
   public MultipartBody getBooks2() {
      List<Attachment> atts = new LinkedList<Attachment>();
      atts.add(new Attachment("root", "application/json", 
         new JSONBook()));
      atts.add(new Attachment("image", "application/octet-stream", 
         getImageInputStream()));
      return new MultipartBody(atts, true);  
   }

}

Similarly to the method returning a list in a previous code fragment, getBooks() will have the response serialized as multiparts, where the first part will have its Content-ID header set to "root.message@cxf.apache.org", the next parts will have ids like '1', '2', etc.

In getBooks2() one can control the content ids of individual parts.

You can also control the contentId and the media type of the root attachment by using a Multipart annotation:

public class Resource {
   @Produces("multipart/form-data")
   @Multipart(value = "root", type = "application/octet-stream") 
   public File testGetImageFromForm() {
      return getClass().getResource("image.png").getFile();
   }
}

One can also have lists or maps of DataHandler, DataSource, Attachment, byte arrays or InputStreams handled as multiparts.

On the client side multiparts can be written the same way. For example:

WebClient client = WebClient.create("http://books");
client.type("multipart/mixed").accept("multipart/mixed");
List<Attachment> atts = new LinkedList<Attachment>();
atts.add(new Attachment("root", "application/json", new JSONBook()));
atts.add(new Attachment("image", "application/octet-stream", 
   getImageInputStream()));
List<Attachment> atts = client.postAndGetCollection(atts, 
   Attachment.class);

When using proxies, a Multipart annotation attached to a method parameter can also be used to set the root contentId and media type. Proxies do not support at the moment multiple method parameters annotated with Multipart (as opposed to the server side) but only a single multipart parameter:

public class Resource {
   @Produces("multipart/mixed")
   @Consumes("multipart/form-data")
   @Multipart(value = "root", type = "application/octet-stream") 
   public File postGetFile(@Multipart(value = "root2", 
      type = "application/octet-stream") File file) {}
}

A method-level Multipart annotation will affect the writing on the server side and the reading on the client side. A parameter-level Multipart annotation will affect writing on the client (proxy) side and reading on the server side. You don't have to use Multipart annotations.

Did this page help you?

If you find any issues with this page or its content – a typo, a missing step, or a technical error – let us know how we can improve!