Download multiple files and metadata using CXF

I need to create a file upload handler as a REST web service using CXF. I was able to upload a single metadata file using the following code:

@POST @Path("/uploadImages") @Consumes(MediaType.MULTIPART_FORM_DATA) public Response uploadImage(@Multipart("firstName") String firstName, @Multipart("lastName") String lastName, List<Attachment> attachments) { for (Attachment att : attachments) { if (att.getContentType().getType().equals("image")) { InputStream is = att.getDataHandler().getInputStream(); // read and store image file } } return Response.ok().build(); } 

Now I need to add support for downloading multiple files in the same request. In this case, instead of an attachment with the image/jpeg content type, I get an attachment with the multipart/mixed content type, which itself contains the individual image/jpeg attachments that I need.

I saw examples for loading multiple JSON or JAXB objects with metadata, but I was not able to get anything to work with binary image data. I tried using MultipartBody directly, but it only returns the multipart/mixed attachment, not the image/jpeg attachments attached to it.

Is there a way to recursively parse a multipart/mixed attachment to get inline attachments? I can, of course, get the multipart/mixed input stream and parse the files myself, but I hope there is a better way.

UPDATE

It seems kludgey, but the next bit of code is good enough. I would like to see a better way though.

 for (Attachment att : attachments) { LOG.debug("attachment content type: {}", att.getContentType().toString()); if (att.getContentType().getType().equals("multipart")) { String ct = att.getContentType().toString(); Message msg = new MessageImpl(); msg.put(Message.CONTENT_TYPE, ct); msg.setContent(InputStream.class, att.getDataHandler().getInputStream()); AttachmentDeserializer ad = new AttachmentDeserializer(msg, Arrays.asList(ct)); ad.initializeAttachments(); // store the first embedded attachment storeFile(msg.getContent(InputStream.class)); // store remaining embedded attachments for (org.apache.cxf.message.Attachment child : msg.getAttachments()) { storeFile(child.getDataHandler().getInputStream()); } } else if (att.getContentType().getType().equals("image")) { storeFile(att.getDataHandler().getInputStream()); } } 
+6
java rest jax-rs cxf
source share
1 answer

I created a similar service to upload multiple images. My implementation is as follows (maybe this helps)

 @Consumes({MediaType.MULTIPART_FORM_DATA,"multipart/mixed" }) public Response uploadImages(final List<Attachment> attachments) { Map<String, InputStream> imageMap = new HashMap<String, InputStream>(); for (Attachment attachment : attachments) { String imageName = attachment.getContentDisposition().getParameter("filename"); if (imageName == null) { imageName = UUID.randomUUID().toString(); } InputStream image = attachment.getDataHandler().getInputStream(); imageMap.put(imageName, image); } return imageMap; } 

if someone prefers bye arrays instead of input streams, it can be easily converted using this helper method

 private static byte[] extractByteArray(final InputStream inputStream) throws IOException { ByteArrayOutputStream buffer = new ByteArrayOutputStream(); byte[] dataChunk = new byte[1024 * 16]; int numRead = 0; while (numRead != -1) { numRead = inputStream.read(dataChunk, 0, dataChunk.length); if (numRead != -1) { buffer.write(dataChunk, 0, numRead); } } buffer.flush(); return buffer.toByteArray(); } 
0
source share

All Articles